diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/mozconfig.automation thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/mozconfig.automation --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/mozconfig.automation 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/mozconfig.automation 2014-11-26 21:44:57.000000000 +0000 @@ -10,13 +10,10 @@ # overridden by setting them earlier in the appropriate mozconfig. mk_add_options "export MOZ_AUTOMATION_BUILD_SYMBOLS=${MOZ_AUTOMATION_BUILD_SYMBOLS-1}" -mk_add_options "export MOZ_AUTOMATION_CHECK=${MOZ_AUTOMATION_CHECK-1}" mk_add_options "export MOZ_AUTOMATION_L10N_CHECK=${MOZ_AUTOMATION_L10N_CHECK-1}" mk_add_options "export MOZ_AUTOMATION_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}" mk_add_options "export MOZ_AUTOMATION_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-1}" mk_add_options "export MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-0}" -mk_add_options "export MOZ_AUTOMATION_TALOS_SENDCHANGE=${MOZ_AUTOMATION_TALOS_SENDCHANGE-1}" -mk_add_options "export MOZ_AUTOMATION_UNITTEST_SENDCHANGE=${MOZ_AUTOMATION_UNITTEST_SENDCHANGE-1}" mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}" mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}" mk_add_options "export MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-0}" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/mozconfig.vs2010-common thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/mozconfig.vs2010-common --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/mozconfig.vs2010-common 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/mozconfig.vs2010-common 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -# Pymake needs Windows-style paths. Use cmd.exe to hack around this. -mk_export_correct_style() { - mk_add_options "export $1=$(cmd.exe //c echo %$1%)" -} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/mozconfig.vs-common thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/mozconfig.vs-common --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/mozconfig.vs-common 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/mozconfig.vs-common 2014-11-26 21:44:57.000000000 +0000 @@ -0,0 +1,4 @@ +# Pymake needs Windows-style paths. Use cmd.exe to hack around this. +mk_export_correct_style() { + mk_add_options "export $1=$(cmd.exe //c echo %$1%)" +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/unix/uniq.pl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/unix/uniq.pl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/unix/uniq.pl 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/unix/uniq.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -#!/usr/bin/env perl - -# 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/. - -##----------------------------## -##---] CORE/CPAN INCLUDES [---## -##----------------------------## -use strict; -use warnings; -use Getopt::Long; - -##-------------------## -##---] EXPORTS [---## -##-------------------## -our $VERSION = qw(1.1); - -##-------------------## -##---] GLOBALS [---## -##-------------------## -my %argv; -my $modver = $Getopt::Long::VERSION || 0; -my $isOldGetopt = ($modver eq '2.25') ? 1 : 0; - -########################################################################### -## Intent: Script init function -########################################################################### -sub init -{ - if ($isOldGetopt) - { - # mozilla.build/mingw perl in need of an upgrade - # emulate Getopt::Long switch|short:init - foreach (qw(debug regex sort)) - { - if (defined($argv{$_})) - { - $argv{$_} ||= 1; - } - } - } -} # init - -##----------------## -##---] MAIN [---## -##----------------## -my @args = ($isOldGetopt) - ? qw(debug|d regex|r sort|s) - : qw(debug|d:1 regex|r:1 sort|s:1) - ; - -unless(GetOptions(\%argv, @args)) -{ - print "Usage: $0\n"; - print " --sort Sort list elements early\n"; - print " --regex Exclude subdirs by pattern\n"; -} - -init(); -my $debug = $argv{debug} || 0; - -my %seen; -my @out; -my @in = ($argv{sort}) ? sort @ARGV : @ARGV; - -foreach my $d (@in) -{ - next if ($seen{$d}++); - - print " arg is $d\n" if ($debug); - - if ($argv{regex}) - { - my $found = 0; - foreach my $dir (@out) - { - my $dirM = quotemeta($dir); - $found++, last if ($d eq $dir || $d =~ m!^${dirM}\/!); - } - print "Adding $d\n" if ($debug && !$found); - push @out, $d if (!$found); - } else { - print "Adding: $d\n" if ($debug); - push(@out, $d); - } -} - -print "@out\n" - -# EOF diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/win32/mozconfig.vs2010 thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/win32/mozconfig.vs2010 --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/win32/mozconfig.vs2010 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/win32/mozconfig.vs2010 2014-11-26 21:44:57.000000000 +0000 @@ -4,7 +4,7 @@ export PATH="/d/msvs10/VSTSDB/Deploy:/d/msvs10/Common7/IDE/:/d/msvs10/VC/BIN:/d/msvs10/Common7/Tools:/d/msvs10/VC/VCPackages:${PATH}" export WIN32_REDIST_DIR=/d/msvs10/VC/redist/x86/Microsoft.VC100.CRT -. $topsrcdir/build/mozconfig.vs2010-common +. $topsrcdir/build/mozconfig.vs-common mk_export_correct_style LIB mk_export_correct_style LIBPATH diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/win32/mozconfig.vs2010-win64 thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/win32/mozconfig.vs2010-win64 --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/win32/mozconfig.vs2010-win64 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/win32/mozconfig.vs2010-win64 2014-11-26 21:44:57.000000000 +0000 @@ -25,7 +25,7 @@ ## WindowsSDKDir ## export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.0/" -. $topsrcdir/build/mozconfig.vs2010-common +. $topsrcdir/build/mozconfig.vs-common mk_export_correct_style LIB mk_export_correct_style LIBPATH diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/win64/mozconfig.vs2010 thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/win64/mozconfig.vs2010 --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/build/win64/mozconfig.vs2010 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/build/win64/mozconfig.vs2010 2014-11-26 21:44:57.000000000 +0000 @@ -31,7 +31,7 @@ export LD=c:/tools/msvs10/VC/BIN/x86_amd64/link.exe fi -. $topsrcdir/build/mozconfig.vs2010-common +. $topsrcdir/build/mozconfig.vs-common mk_export_correct_style LIB mk_export_correct_style LIBPATH diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/content/agenda-listbox.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/content/agenda-listbox.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/content/agenda-listbox.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/content/agenda-listbox.js 2014-11-26 21:44:57.000000000 +0000 @@ -12,7 +12,7 @@ var agendaListbox = { agendaListboxControl: null, - pendingRefresh: null, + mPendingRefreshJobs: null, kDefaultTimezone: null, showsToday: false }; @@ -33,6 +33,7 @@ var soondays = Preferences.get("calendar.agendaListbox.soondays", 5); this.soon = new Synthetic(showSoonHeader, soondays); this.periods = [this.today, this.tomorrow, this.soon]; + this.mPendingRefreshJobs = new Map(); // Make sure the agenda listbox is unloaded var self = this; @@ -603,35 +604,86 @@ */ agendaListbox.refreshCalendarQuery = function refreshCalendarQuery(aStart, aEnd, aCalendar) { - let pendingRefresh = cal.wrapInstance(this.pendingRefresh, Components.interfaces.calIOperation); - if (this.pendingRefresh) { - if (pendingRefresh) { - this.pendingRefresh = null; - pendingRefresh.cancel(null); - } else { - return; - } - } - if (!(aStart || aEnd || aCalendar)) { - this.removeListItems(); - } - if (!aStart) { - aStart = this.getStart(); - } - if (!aEnd) { - aEnd = this.getEnd(); - } - if (aStart && aEnd) { - var filter = this.calendar.ITEM_FILTER_CLASS_OCCURRENCES | - this.calendar.ITEM_FILTER_TYPE_EVENT; - this.pendingRefresh = true; - let refreshCalendar = aCalendar || this.calendar; - pendingRefresh = refreshCalendar.getItems(filter, 0, aStart, aEnd, - this.calendarOpListener); - if (pendingRefresh && pendingRefresh.isPending) { // support for calIOperation - this.pendingRefresh = pendingRefresh; + let refreshJob = { + agendaListbox: this, + calendar: null, + calId: null, + operation: null, + cancelled: false, + + onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDateTime) { + if (this.agendaListbox.mPendingRefreshJobs.has(this.calId)) { + this.agendaListbox.mPendingRefreshJobs.delete(this.calId); + } + + if (!this.cancelled) { + setCurrentEvent(); + } + }, + + onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) { + if (this.cancelled || !Components.isSuccessCode(aStatus)) { + return; + } + for (let item of aItems) { + this.agendaListbox.addItem(item); + } + }, + + cancel: function() { + this.cancelled = true; + if (this.operation && this.operation.isPending) { + this.operation.cancel(); + this.operation = null; + } + }, + + execute: function(aStart, aEnd, aCalendar) { + if (!(aStart || aEnd || aCalendar)) { + this.agendaListbox.removeListItems(); + } + + if (!aCalendar) { + aCalendar = this.agendaListbox.calendar; + } + if (!aStart) { + aStart = this.agendaListbox.getStart(); + } + if (!aEnd) { + aEnd = this.agendaListbox.getEnd(); + } + if (!(aStart || aEnd || aCalendar)) { + return; + } + + if (aCalendar.type == "composite") { + // we're refreshing from the composite calendar, so we can cancel + // all other pending refresh jobs. + this.calId = "composite"; + for (let job of this.agendaListbox.mPendingRefreshJobs.values()) { + job.cancel(); + } + this.agendaListbox.mPendingRefreshJobs.clear(); + } else { + this.calId = aCalendar.id; + if (this.agendaListbox.mPendingRefreshJobs.has(this.calId)) { + this.agendaListbox.mPendingRefreshJobs.get(this.calId).cancel(); + this.agendaListbox.mPendingRefreshJobs.delete(this.calId); + } + } + this.calendar = aCalendar; + + let filter = this.calendar.ITEM_FILTER_CLASS_OCCURRENCES | + this.calendar.ITEM_FILTER_TYPE_EVENT; + let op = this.calendar.getItems(filter, 0, aStart, aEnd, this); + if (op && op.isPending) { + this.operation = op; + this.agendaListbox.mPendingRefreshJobs.set(this.calId, this); + } } - } + }; + + refreshJob.execute(aStart, aEnd, aCalendar); }; /** @@ -830,29 +882,6 @@ }; /** - * Called when all items have been retrieved from the calendar. - * @see calIOperationListener - */ -agendaListbox.calendarOpListener.onOperationComplete = -function listener_onOperationComplete(calendar, status, optype, id, - detail) { - // signal that the current operation finished. - this.agendaListbox.pendingRefresh = null; - setCurrentEvent(); -}; - -/** - * Called when an item has been retrieved, adds all items to the agenda listbox. - * @see calIOperationListener - */ -agendaListbox.calendarOpListener.onGetResult = -function listener_onGetResult(calendar, status, itemtype, detail, count, items) { - if (!Components.isSuccessCode(status)) - return; - items.forEach(this.agendaListbox.addItem, this.agendaListbox); -}; - -/** * Calendar and composite observer, used to keep agenda listbox up to date. * @see calIObserver * @see calICompositeObserver diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/content/calendar-calendars-list.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/content/calendar-calendars-list.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/content/calendar-calendars-list.xul 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/content/calendar-calendars-list.xul 2014-11-26 21:44:57.000000000 +0000 @@ -14,6 +14,17 @@ + + + + 1) { enableElement("list-calendars-context-delete"); } + + enableElement("list-calendars-context-togglevisible"); + setElementValue("list-calendars-context-togglevisible", false, "collapsed"); + let stringName = composite.getCalendarById(calendar.id) ? "hideCalendar" : "showCalendar"; + setElementValue("list-calendars-context-togglevisible", + cal.calGetString("calendar", stringName, [calendar.name]), + "label"); + enableElement("list-calendars-context-showonly"); + setElementValue("list-calendars-context-showonly", false, "collapsed"); + setElementValue("list-calendars-context-showonly", + cal.calGetString("calendar", "showOnlyCalendar", [calendar.name]), + "label"); } else { disableElement("list-calendars-context-edit"); disableElement("list-calendars-context-publish"); disableElement("list-calendars-context-delete"); + disableElement("list-calendars-context-togglevisible"); + setElementValue("list-calendars-context-togglevisible", true, "collapsed"); + disableElement("list-calendars-context-showonly"); + setElementValue("list-calendars-context-showonly", true, "collapsed"); } return true; } @@ -195,6 +212,55 @@ document.getElementById("calendar-list-tree-widget").ensureCalendarVisible(aCalendar); } +/** + * Hides the specified calendar if it is visible, or shows it if it is hidden. + * + * @param aCalendar The calendar to show or hide + */ +function toggleCalendarVisible(aCalendar) { + let composite = getCompositeCalendar(); + if (composite.getCalendarById(aCalendar.id)) { + composite.removeCalendar(aCalendar); + } else { + composite.addCalendar(aCalendar); + } +} + +/** + * Shows all hidden calendars. + */ +function showAllCalendars() { + let composite = getCompositeCalendar(); + let cals = cal.getCalendarManager().getCalendars({}); + + composite.startBatch(); + for (let calendar of cals) { + if (!composite.getCalendarById(calendar.id)) { + composite.addCalendar(calendar); + } + } + composite.endBatch(); +} + +/** + * Shows only the specified calendar, and hides all others. + * + * @param aCalendar The calendar to show as the only visible calendar + */ +function showOnlyCalendar(aCalendar) { + let composite = getCompositeCalendar(); + let cals = composite.getCalendars({}) || []; + + composite.startBatch(); + for (let calendar of cals) { + if (calendar.id != aCalendar.id) { + composite.removeCalendar(calendar); + } + } + composite.addCalendar(aCalendar); + composite.endBatch(); +} + var compositeObserver = { QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIObserver, Components.interfaces.calICompositeObserver]), diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/modules/calUtils.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/modules/calUtils.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/modules/calUtils.jsm 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/modules/calUtils.jsm 2014-11-26 21:44:57.000000000 +0000 @@ -6,7 +6,7 @@ var gCalThreadingEnabled; -Components.utils.import("resource:///modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Preferences.jsm"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/src/calDeletedItems.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/src/calDeletedItems.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/src/calDeletedItems.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/src/calDeletedItems.js 2014-11-26 21:44:57.000000000 +0000 @@ -3,8 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ Components.utils.import("resource://calendar/modules/calUtils.jsm"); -Components.utils.import("resource:///modules/XPCOMUtils.jsm"); -Components.utils.import("resource:///modules/FileUtils.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/FileUtils.jsm"); /** * Handles remembering deleted items. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/src/calRecurrenceDate.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/src/calRecurrenceDate.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/base/src/calRecurrenceDate.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/base/src/calRecurrenceDate.js 2014-11-26 21:44:57.000000000 +0000 @@ -2,7 +2,7 @@ * 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/. */ -Components.utils.import("resource:///modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://calendar/modules/calUtils.jsm"); function calRecurrenceDate() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/locales/en-US/chrome/calendar/calendar.dtd thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/locales/en-US/chrome/calendar/calendar.dtd --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/locales/en-US/chrome/calendar/calendar.dtd 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/locales/en-US/chrome/calendar/calendar.dtd 2014-11-26 21:44:58.000000000 +0000 @@ -243,6 +243,16 @@ + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/locales/en-US/chrome/calendar/calendar.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/locales/en-US/chrome/calendar/calendar.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/locales/en-US/chrome/calendar/calendar.properties 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/locales/en-US/chrome/calendar/calendar.properties 2014-11-26 21:44:58.000000000 +0000 @@ -589,3 +589,12 @@ unitMinutes=#1 minute;#1 minutes unitHours=#1 hour;#1 hours unitDays=#1 day;#1 days + +# LOCALIZATION NOTE (showCalendar) +# Used in calendar list context menu +# %1$S will be replaced with the calendar name +# uses the access key calendar.context.togglevisible.accesskey +showCalendar=Show %1$S +hideCalendar=Hide %1$S +# uses the access key calendar.context.showonly.accesskey +showOnlyCalendar=Show Only %1$S diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/providers/storage/calStorageUpgrade.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/providers/storage/calStorageUpgrade.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/providers/storage/calStorageUpgrade.jsm 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/providers/storage/calStorageUpgrade.jsm 2014-11-26 21:44:58.000000000 +0000 @@ -66,7 +66,7 @@ * please file a bug. */ -Components.utils.import("resource:///modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://calendar/modules/calUtils.jsm"); Components.utils.import("resource://calendar/modules/calStorageHelpers.jsm"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/mozmill/testAlarmDefaultValue.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/mozmill/testAlarmDefaultValue.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/mozmill/testAlarmDefaultValue.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/mozmill/testAlarmDefaultValue.js 2014-11-26 21:44:58.000000000 +0000 @@ -8,7 +8,7 @@ */ Components.utils.import("resource://calendar/modules/calUtils.jsm"); -Components.utils.import("resource:///modules/PluralForm.jsm"); +Components.utils.import("resource://gre/modules/PluralForm.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); var MODULE_NAME = "testAlarmDefaultValue"; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/unit/test_alarmservice.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/unit/test_alarmservice.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/unit/test_alarmservice.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/unit/test_alarmservice.js 2014-11-26 21:44:58.000000000 +0000 @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ Components.utils.import("resource://calendar/modules/calUtils.jsm"); -Components.utils.import("resource:///modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); const EXPECT_NONE = 0; const EXPECT_FIRED = 1; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/unit/test_freebusy_service.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/unit/test_freebusy_service.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/unit/test_freebusy_service.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/unit/test_freebusy_service.js 2014-11-26 21:44:58.000000000 +0000 @@ -2,7 +2,7 @@ * 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/. */ -Components.utils.import("resource:///modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://calendar/modules/calProviderUtils.jsm"); const cIFI = Components.interfaces.calIFreeBusyInterval; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/unit/test_search_service.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/unit/test_search_service.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/calendar/test/unit/test_search_service.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/calendar/test/unit/test_search_service.js 2014-11-26 21:44:58.000000000 +0000 @@ -2,7 +2,7 @@ * 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/. */ -Components.utils.import("resource:///modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); const HINT_EXACT_MATCH = Components.interfaces.calICalendarSearchProvider.HINT_EXACT_MATCH; let search = Components.classes["@mozilla.org/calendar/calendarsearch-service;1"] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/components/public/imIAccount.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/components/public/imIAccount.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/components/public/imIAccount.idl 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/components/public/imIAccount.idl 2014-11-26 21:44:58.000000000 +0000 @@ -259,7 +259,10 @@ attribute short firstConnectionState; - // Passwords are stored in the toolkit Password Manager. + /* Passwords are stored in the toolkit Password Manager. + * Warning: Don't attempt to access passwords during startup before + * Services.login.initializationPromise has resolved. + */ attribute AUTF8String password; attribute AUTF8String alias; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/components/src/imAccounts.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/components/src/imAccounts.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/components/src/imAccounts.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/components/src/imAccounts.js 2014-11-26 21:44:58.000000000 +0000 @@ -161,23 +161,25 @@ if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_PENDING) this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_CRASHED; - // Try to convert old passwords stored in the preferences. - // Don't try too hard if the user has canceled a master password prompt: - // we don't want to display several of theses prompts at startup. - if (gConvertingOldPasswords && !this.protocol.noPassword) { - try { - let password = this.prefBranch.getComplexValue(kPrefAccountPassword, - Ci.nsISupportsString).data; - if (password && !this.password) - this.password = password; - } catch (e) { /* No password saved in the prefs for this account. */ } - } + Services.logins.initializationPromise.then(() => { + // Try to convert old passwords stored in the preferences. + // Don't try too hard if the user has canceled a master password prompt: + // we don't want to display several of theses prompts at startup. + if (gConvertingOldPasswords && !this.protocol.noPassword) { + try { + let password = this.prefBranch.getComplexValue(kPrefAccountPassword, + Ci.nsISupportsString).data; + if (password && !this.password) + this.password = password; + } catch (e) { /* No password saved in the prefs for this account. */ } + } - // Check for errors that should prevent connection attempts. - if (this._passwordRequired && !this.password) - this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD; - else if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_CRASHED) - this._connectionErrorReason = Ci.imIAccount.ERROR_CRASHED; + // Check for errors that should prevent connection attempts. + if (this._passwordRequired && !this.password) + this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD; + else if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_CRASHED) + this._connectionErrorReason = Ci.imIAccount.ERROR_CRASHED; + }); } imAccount.prototype = { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/components/src/imCore.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/components/src/imCore.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/components/src/imCore.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/components/src/imCore.js 2014-11-26 21:44:58.000000000 +0000 @@ -268,8 +268,13 @@ Services.conversations.initConversations(); Services.obs.notifyObservers(this, "prpl-init", null); - if (accounts.autoLoginStatus == Ci.imIAccountsService.AUTOLOGIN_ENABLED) - accounts.processAutoLogin(); + // Wait with automatic connections until the password service + // is available. + if (accounts.autoLoginStatus == Ci.imIAccountsService.AUTOLOGIN_ENABLED) { + Services.logins.initializationPromise.then(() => { + Services.accounts.processAutoLogin(); + }); + } }, observe: function(aObject, aTopic, aData) { if (aTopic == kQuitApplicationGranted) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/modules/imContentSink.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/modules/imContentSink.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/modules/imContentSink.jsm 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/modules/imContentSink.jsm 2014-11-26 21:44:58.000000000 +0000 @@ -102,7 +102,7 @@ styles: { 'font-style': true, 'font-weight': true, - '-moz-text-decoration-line': true + 'text-decoration-line': true } }; @@ -150,9 +150,9 @@ 'font-size': true, 'font-style': true, 'font-weight': true, - '-moz-text-decoration-color': true, - '-moz-text-decoration-style': true, - '-moz-text-decoration-line': true + 'text-decoration-color': true, + 'text-decoration-style': true, + 'text-decoration-line': true } }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/modules/test/test_filtering.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/modules/test/test_filtering.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/modules/test/test_filtering.js 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/modules/test/test_filtering.js 2014-11-26 21:44:58.000000000 +0000 @@ -148,8 +148,8 @@ let string = "foo"; do_check_eq(string, cleanupImMarkup(string)); } - // text-decoration is a shorthand for several -moz-text-decoration properties. - do_check_eq("foo", + // text-decoration is a shorthand for several text-decoration properties. + do_check_eq("foo", cleanupImMarkup("foo")); const badCSS = [ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/irc/ircBase.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/irc/ircBase.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/irc/ircBase.jsm 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/irc/ircBase.jsm 2014-11-26 21:44:58.000000000 +0000 @@ -204,13 +204,11 @@ conversation.joining = false; // If the user parted from this room earlier, confirm the rejoin. - // If conversation.chatRoomFields is present, the rejoin was due to - // an automatic reconnection, for which we already notify the user. - if (!conversation._firstJoin && !conversation.chatRoomFields) { + if (conversation._rejoined) { conversation.writeMessage(aMessage.origin, _("message.rejoined"), {system: true}); + delete conversation._rejoined; } - delete conversation._firstJoin; // Ensure chatRoomFields information is available for reconnection. if (!conversation.chatRoomFields) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/irc/irc.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/irc/irc.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/irc/irc.js 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/irc/irc.js 2014-11-26 21:44:58.000000000 +0000 @@ -110,15 +110,6 @@ } } -// This copies all the properties of aBase to aPrototype (which is expected to -// be the prototype of an object). This is necessary because JavaScript does not -// support multiple inheritance and both conversation objects have a lot of -// shared code (but inherit from objects exposing different XPCOM interfaces). -function copySharedBaseToPrototype(aBase, aPrototype) { - for (let property in aBase) - aPrototype[property] = aBase[property]; -} - // Properties / methods shared by both ircChannel and ircConversation. const GenericIRCConversation = { _observedNicks: [], @@ -276,7 +267,6 @@ this._modes = new Set(); this._observedNicks = []; this.banMasks = []; - this._firstJoin = true; } ircChannel.prototype = { __proto__: GenericConvChatPrototype, @@ -285,8 +275,8 @@ // For IRC you're not in a channel until the JOIN command is received, open // all channels (initially) as left. _left: true, - // True until successfully joined for the first time. - _firstJoin: false, + // True while we are rejoining a channel previously parted by the user. + _rejoined: false, banMasks: [], // Overwrite the writeMessage function to apply CTCP formatting before @@ -555,7 +545,7 @@ return !this._modes.has("t") || participant.op || participant.halfOp; } }; -copySharedBaseToPrototype(GenericIRCConversation, ircChannel.prototype); +Object.assign(ircChannel.prototype, GenericIRCConversation); function ircParticipant(aName, aConv) { this._name = aName; @@ -628,7 +618,7 @@ this.notifyObservers(null, "update-conv-title"); } }; -copySharedBaseToPrototype(GenericIRCConversation, ircConversation.prototype); +Object.assign(ircConversation.prototype, GenericIRCConversation); function ircSocket(aAccount) { this._account = aAccount; @@ -1512,11 +1502,16 @@ if (this.channelPrefixes.indexOf(channel[0]) == -1) channel = "#" + channel; - // No need to join a channel we are already in. if (this.conversations.has(channel)) { let conv = this.getConversation(channel); - if (!conv.left) + if (!conv.left) { + // No need to join a channel we are already in. return conv; + } + else if (!conv.chatRoomFields) { + // We are rejoining a channel that was parted by the user. + conv._rejoined = true; + } } let params = [channel]; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/yahoo/test/test_yahooAccount.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/yahoo/test/test_yahooAccount.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/yahoo/test/test_yahooAccount.js 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/yahoo/test/test_yahooAccount.js 2014-11-26 21:44:58.000000000 +0000 @@ -1,7 +1,7 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -Components.utils.import("resource:///modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); let yahoo = {}; Services.scriptloader.loadSubScript("resource:///components/yahoo.js", yahoo); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/yahoo/test/test_yahooLoginHelper.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/yahoo/test/test_yahooLoginHelper.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/yahoo/test/test_yahooLoginHelper.js 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/yahoo/test/test_yahooLoginHelper.js 2014-11-26 21:44:58.000000000 +0000 @@ -2,7 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ Components.utils.import("resource:///modules/ArrayBufferUtils.jsm"); -Components.utils.import("resource:///modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource:///modules/yahoo-session.jsm"); let yahoo = {}; Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/yahoo/test/test_yahoopacket.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/yahoo/test/test_yahoopacket.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/chat/protocols/yahoo/test/test_yahoopacket.js 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/chat/protocols/yahoo/test/test_yahoopacket.js 2014-11-26 21:44:58.000000000 +0000 @@ -2,7 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ Components.utils.import("resource:///modules/ArrayBufferUtils.jsm"); -Components.utils.import("resource:///modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource:///modules/yahoo-session.jsm"); let yahoo = {}; Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/config/config.mk thunderbird-trunk-36.0~a1~hg20141126r17147.217518/config/config.mk --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/config/config.mk 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/config/config.mk 2014-11-26 21:44:59.000000000 +0000 @@ -275,10 +275,6 @@ endif # MOZ_PROFILE_USE endif # NO_PROFILE_GUIDED_OPTIMIZE -ifdef _MSC_VER -OS_LDFLAGS += $(DELAYLOAD_LDFLAGS) -endif # _MSC_VER - # Does the makefile specifies the internal XPCOM API linkage? ifneq (,$(MOZILLA_INTERNAL_API)$(LIBXUL_LIBRARY)) DEFINES += -DMOZILLA_INTERNAL_API @@ -676,24 +672,6 @@ endif EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB) -# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo) -# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker -# arguments syntax. Should only be used for system libraries - -# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir) -# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX) - -# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo) -# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX) - -ifdef GNU_CC -EXPAND_LIBNAME = $(addprefix -l,$(1)) -else -EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) -endif -EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) -EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) - # Include internal ply only if needed ifndef MOZ_SYSTEM_PLY PLY_INCLUDE = -I$(MOZILLA_DIR)/other-licenses/ply diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/config/rules.mk thunderbird-trunk-36.0~a1~hg20141126r17147.217518/config/rules.mk --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/config/rules.mk 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/config/rules.mk 2014-11-26 21:44:59.000000000 +0000 @@ -111,7 +111,7 @@ ifdef FORCE_SHARED_LIB # ... except when we really want one ifdef NO_EXPAND_LIBS -LIBRARY := $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) +LIBRARY := $(REAL_LIBRARY) else LIBRARY := $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) endif @@ -120,9 +120,13 @@ ifeq (,$(SDK_LIBRARY)$(DIST_INSTALL)$(NO_EXPAND_LIBS)) LIBRARY := $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) else +ifdef NO_EXPAND_LIBS +LIBRARY := $(REAL_LIBRARY) +else LIBRARY := $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) endif endif +endif endif # REAL_LIBRARY endif # LIBRARY @@ -442,12 +446,6 @@ OS_CPPFLAGS += -DPATH_MAX=1024 -DMAXPATHLEN=1024 endif -ifeq ($(OS_ARCH),WINNT) -ifdef USE_DELAYIMP -OS_LIBS += $(call EXPAND_LIBNAME,delayimp) -endif -endif - # # MINGW32 # @@ -791,7 +789,8 @@ endif $(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(STATIC_LIBS_DEPS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS)) $(EXTRA_DEPS) $(GLOBAL_DEPS) - $(RM) $(LIBRARY) +# Always remove both library and library descriptor + $(RM) $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) $(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(STATIC_LIBS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS)) $(RANLIB) $@ @@ -1198,10 +1197,11 @@ ifndef NO_DIST_INSTALL _XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME) _XPT_NAME_DEST := $(FINAL_TARGET)/components +_XPT_NAME_TARGET := misc INSTALL_TARGETS += _XPT_NAME ifndef NO_INTERFACES_MANIFEST -libs:: $(call mkdir_deps,$(FINAL_TARGET)/components) +misc:: $(call mkdir_deps,$(FINAL_TARGET)/components) $(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest 'interfaces $(XPT_NAME)') $(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/interfaces.manifest') endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/build/config.mk thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/build/config.mk --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/build/config.mk 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/build/config.mk 2014-11-26 22:48:04.000000000 +0000 @@ -28,8 +28,6 @@ # Define other variables used throughout the build MOZ_DEFAULT_APP_NAME ?= $(MOZ_PKG_BASENAME) -MOZ_APP_BASENAME ?= $(shell echo $(MOZ_APP_NAME) | sed -n 's/\-.\|\<./\U&/g p') -MOZ_DEFAULT_APP_BASENAME ?= $(shell echo $(MOZ_DEFAULT_APP_NAME) | sed -n 's/\-.\|\<./\U&/g p') MOZ_FORCE_UNOFFICIAL_BRANDING = 0 @@ -49,8 +47,8 @@ MOZ_FORCE_UNOFFICIAL_BRANDING = 1 endif -ifneq ($(MOZ_APP_NAME)$(MOZ_APP_BASENAME),$(MOZ_DEFAULT_APP_NAME)$(MOZ_DEFAULT_APP_BASENAME)) -# If we change MOZ_APP_NAME or MOZ_APP_BASENAME, don't use official branding +ifneq ($(MOZ_APP_NAME),$(MOZ_DEFAULT_APP_NAME)) +# If we change MOZ_APP_NAME, don't use official branding MOZ_FORCE_UNOFFICIAL_BRANDING = 1 endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/build/rules.mk thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/build/rules.mk --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/build/rules.mk 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/build/rules.mk 2014-11-26 22:48:04.000000000 +0000 @@ -2,7 +2,7 @@ # We need this to execute before the debian/control target gets called # and before patches are unapplied -clean:: restore-upstream-files +clean:: ifneq (1, $(MOZ_DISABLE_CLEAN_CHECKS)) cp debian/control debian/control.old touch debian/control.in @@ -63,15 +63,14 @@ MOZ_APP_SUBDIR ?= -# The profile directory is determined from the Vendor and Name fields of -# the application.ini -ifeq (,$(MOZ_VENDOR)) -PROFILE_BASE = -else +# If we change MOZ_APP_NAME, we want to set the profile directory +# to match +ifneq (,$(MOZ_VENDOR)) PROFILE_BASE = $(shell echo $(MOZ_VENDOR) | tr A-Z a-z)/ endif -MOZ_PROFILEDIR := .$(PROFILE_BASE)$(shell echo $(MOZ_APP_BASENAME) | tr A-Z a-z) -MOZ_DEFAULT_PROFILEDIR := .$(PROFILE_BASE)$(shell echo $(MOZ_DEFAULT_APP_BASENAME) | tr A-Z a-z) +ifneq ($(MOZ_APP_NAME),$(MOZ_DEFAULT_APP_NAME)) +MOZ_APP_PROFILE := .$(PROFILE_BASE)$(MOZ_APP_NAME) +endif DEB_AUTO_UPDATE_DEBIAN_CONTROL = no @@ -132,16 +131,17 @@ MOZ_PKG_SUPPORT_SUGGESTS ?= # Defines used for the Mozilla text preprocessor -MOZ_DEFINES += -DMOZ_LIBDIR="$(MOZ_LIBDIR)" -DMOZ_APP_NAME="$(MOZ_APP_NAME)" -DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \ +MOZ_DEFINES += -DMOZ_LIBDIR="$(MOZ_LIBDIR)" -DMOZ_APP_NAME="$(MOZ_APP_NAME)" \ -DMOZ_INCDIR="$(MOZ_INCDIR)" -DMOZ_IDLDIR="$(MOZ_IDLDIR)" -DMOZ_VERSION="$(MOZ_VERSION)" -DDEB_HOST_ARCH="$(DEB_HOST_ARCH)" \ -DMOZ_DISPLAY_NAME="$(MOZ_DISPLAY_NAME)" -DMOZ_PKG_NAME="$(MOZ_PKG_NAME)" \ -DMOZ_BRANDING_OPTION="$(MOZ_BRANDING_OPTION)" -DTOPSRCDIR="$(CURDIR)" -DDEB_HOST_GNU_TYPE="$(DEB_HOST_GNU_TYPE)" \ -DMOZ_ADDONDIR="$(MOZ_ADDONDIR)" -DMOZ_SDKDIR="$(MOZ_SDKDIR)" -DMOZ_DISTDIR="$(MOZ_DISTDIR)" -DMOZ_UPDATE_CHANNEL="$(CHANNEL)" \ - -DMOZ_OBJDIR="$(MOZ_OBJDIR)" -DDEB_BUILDDIR="$(DEB_BUILDDIR)" -DMOZ_PYTHON="$(MOZ_PYTHON)" -DMOZ_PROFILEDIR="$(MOZ_PROFILEDIR)" \ - -DMOZ_PKG_BASENAME="$(MOZ_PKG_BASENAME)" -DMOZ_DEFAULT_PROFILEDIR="$(MOZ_DEFAULT_PROFILEDIR)" \ - -DMOZ_DEFAULT_APP_NAME="$(MOZ_DEFAULT_APP_NAME)" -DMOZ_DEFAULT_APP_BASENAME="$(MOZ_DEFAULT_APP_BASENAME)" \ - -DDISTRIB_VERSION="$(DISTRIB_VERSION_MAJOR)$(DISTRIB_VERSION_MINOR)" + -DMOZ_OBJDIR="$(MOZ_OBJDIR)" -DDEB_BUILDDIR="$(DEB_BUILDDIR)" -DMOZ_PYTHON="$(MOZ_PYTHON)" -DMOZ_PKG_BASENAME="$(MOZ_PKG_BASENAME)" \ + -DMOZ_DEFAULT_APP_NAME="$(MOZ_DEFAULT_APP_NAME)" -DDISTRIB_VERSION="$(DISTRIB_VERSION_MAJOR)$(DISTRIB_VERSION_MINOR)" +ifneq (,$(MOZ_APP_PROFILE)) +MOZ_DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)" +endif ifeq (1, $(MOZ_ENABLE_BREAKPAD)) MOZ_DEFINES += -DMOZ_ENABLE_BREAKPAD endif @@ -393,29 +393,6 @@ cp debian/config/locales.shipped debian/config/locales.shipped.old pre-build:: debian/config/locales.shipped $(pkgname_subst_files) $(appname_subst_files) mozconfig $(call cmp_auto_generated_file,debian/config/locales.shipped,refresh-supported-locales) -pre-build:: debian/stamp-monkey-patch-upstream-files - -debian/stamp-monkey-patch-upstream-files: - @touch debian/monkey-patch-files - @echo "#!/bin/sh" >> debian/monkey-patch-files.sh - make -f debian/rules monkey-patch-upstream-files - @while read line; do \ - cp $$line $$line.moz-orig; \ - done < debian/monkey-patch-files - sh debian/monkey-patch-files.sh - @rm debian/monkey-patch-files.sh - @touch $@ - -monkey-patch-upstream-files:: - -restore-upstream-files:: - @$(if $(wildcard debian/monkey-patch-files), \ - while read line; do \ - if [ -f $$line.moz-orig ]; then \ - mv $$line.moz-orig $$line; \ - fi \ - done < debian/monkey-patch-files; \ - rm debian/monkey-patch-files) EXTRACT_TARBALL = $(firstword $(shell TMPDIR=`mktemp -d`; tar -jxf $(1) -C $$TMPDIR > /dev/null 2>&1; echo $$TMPDIR/`ls $$TMPDIR/ | head -n1`)) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/changelog thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/changelog --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/changelog 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/changelog 2014-11-26 22:48:04.000000000 +0000 @@ -1,14 +1,32 @@ -thunderbird-trunk (36.0~a1~hg20141114r17084.215607-0ubuntu1~umd1~precise) precise; urgency=medium +thunderbird-trunk (36.0~a1~hg20141126r17147.217518-0ubuntu1~umd1~precise) precise; urgency=medium * Refresh patches - update debian/patches/unity-menubar.patch - update debian/patches/ubuntu-ua-string-changes.patch - update debian/patches/revert-removal-of-native-notifications.patch + - update debian/patches/dont-include-hyphenation-patterns.patch * Disable all of the testsuite related patches and don't install anything in to the testsuite package for now. The patches have all bit-rotted, we're not running any tests and nobody is driving that anymore * Don't do unified builds unconditionally on i386, as they don't crash anymore + * Don't clone the nightly profile from the default profile at startup + - update debian/thunderbird.sh.in + * Don't use --with-app-basename to create the co-installable nightly build + as it's not useful anymore, and changing the application name to + "Thunderbird-Trunk" has always been problematic for code / addons that check + the appname. Continue to use --with-app-name as before (which just changes + the install name and the remoting name), and add a patch to introduce + --with-app-profile, which allows us to change the profile location + - update debian/build/rules.mk + - update debian/build/config.mk + - update debian/config/mozconfig.in + - update debian/rules + - add debian/patches/support-coinstallable-trunk-build.patch + - add debian/patches/set-prgname-to-remoting-name.patch + - update debian/patches/series + * Drop debian/patches/revert-removal-of-native-notifications.patch - fixed + upstream -- Chris Coulson Sat, 01 Nov 2014 01:36:51 +0000 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/config/mozconfig.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/config/mozconfig.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/config/mozconfig.in 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/config/mozconfig.in 2014-11-26 22:48:04.000000000 +0000 @@ -55,6 +55,12 @@ ac_add_options --disable-debug %%endif ac_add_options --disable-elf-hack +%%if MOZ_APP_NAME != MOZ_DEFAULT_APP_NAME +ac_add_options --with-app-name=@MOZ_APP_NAME@ +%%endif +%%ifdef MOZ_APP_PROFILE +ac_add_options --with-app-profile=@MOZ_APP_PROFILE@ +%%endif %%if DEB_HOST_ARCH != i386 %%if DEB_HOST_ARCH != amd64 ac_add_options --disable-webrtc diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/control thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/control --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/control 2014-11-14 10:11:46.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/control 2014-11-26 22:48:09.000000000 +0000 @@ -39,7 +39,7 @@ xvfb, python (>= 2.7), libffi-dev (>= 3.0.9) [arm64] -Build-Conflicts: python-progressbar +#Build-Conflicts: python-progressbar Standards-Version: 3.9.1 #XS-Testsuite: autopkgtest diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/control.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/control.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/control.in 2014-11-14 10:11:46.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/control.in 2014-11-26 22:48:09.000000000 +0000 @@ -39,7 +39,7 @@ xvfb, python (>= 2.7), libffi-dev (>= 3.0.9) [arm64] -Build-Conflicts: python-progressbar +#Build-Conflicts: python-progressbar Standards-Version: 3.9.1 #XS-Testsuite: autopkgtest diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/dont-include-hyphenation-patterns.patch thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/dont-include-hyphenation-patterns.patch --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/dont-include-hyphenation-patterns.patch 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/dont-include-hyphenation-patterns.patch 2014-11-26 22:48:04.000000000 +0000 @@ -8,11 +8,11 @@ --- thunderbird-trunk-22.0~a1~hg20130317r12132.125128.orig/mail/installer/package-manifest.in 2013-03-18 02:59:56.000000000 +0000 +++ thunderbird-trunk-22.0~a1~hg20130317r12132.125128/mail/installer/package-manifest.in 2013-03-18 22:48:38.427893985 +0000 @@ -39,7 +39,7 @@ - @BINPATH@/@PREF_DIR@/all-l10n.js - @BINPATH@/searchplugins/* - @BINPATH@/dictionaries/* --@BINPATH@/hyphenation/* -+; @BINPATH@/hyphenation/* + @RESPATH@/@PREF_DIR@/all-l10n.js + @RESPATH@/searchplugins/* + @RESPATH@/dictionaries/* +-@RESPATH@/hyphenation/* ++; @RESPATH@/hyphenation/* #ifdef XP_WIN32 @BINPATH@/uninstall/helper.exe #endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/revert-removal-of-native-notifications.patch thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/revert-removal-of-native-notifications.patch --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/revert-removal-of-native-notifications.patch 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/revert-removal-of-native-notifications.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,265 +0,0 @@ -# HG changeset patch -# Parent 36da3cb921935478b6a37936b18b5c85a33d5617 -# User Chris Coulson - -Index: thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsAlertsIconListener.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsAlertsIconListener.h 2014-11-03 19:19:05.000000000 +0000 -@@ -0,0 +1,90 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* 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/. */ -+ -+#ifndef nsAlertsIconListener_h__ -+#define nsAlertsIconListener_h__ -+ -+#include "nsCOMPtr.h" -+#include "imgINotificationObserver.h" -+#include "nsStringAPI.h" -+#include "nsIObserver.h" -+#include "nsWeakReference.h" -+ -+#include -+ -+class imgIRequest; -+ -+struct NotifyNotification; -+ -+class nsAlertsIconListener : public imgINotificationObserver, -+ public nsIObserver, -+ public nsSupportsWeakReference -+{ -+public: -+ NS_DECL_ISUPPORTS -+ NS_DECL_IMGINOTIFICATIONOBSERVER -+ NS_DECL_NSIOBSERVER -+ -+ nsAlertsIconListener(); -+ -+ nsresult InitAlertAsync(const nsAString & aImageUrl, -+ const nsAString & aAlertTitle, -+ const nsAString & aAlertText, -+ bool aAlertTextClickable, -+ const nsAString & aAlertCookie, -+ nsIObserver * aAlertListener); -+ -+ void SendCallback(); -+ void SendClosed(); -+ -+private: -+ virtual ~nsAlertsIconListener(); -+ -+protected: -+ nsresult OnStopRequest(imgIRequest* aRequest); -+ nsresult OnStopFrame(imgIRequest* aRequest); -+ -+ /** -+ * The only difference between libnotify.so.4 and libnotify.so.1 for these symbols -+ * is that notify_notification_new takes three arguments in libnotify.so.4 and -+ * four in libnotify.so.1. -+ * Passing the fourth argument as NULL is binary compatible. -+ */ -+ typedef void (*NotifyActionCallback)(NotifyNotification*, char*, gpointer); -+ typedef bool (*notify_is_initted_t)(void); -+ typedef bool (*notify_init_t)(const char*); -+ typedef GList* (*notify_get_server_caps_t)(void); -+ typedef NotifyNotification* (*notify_notification_new_t)(const char*, const char*, const char*, const char*); -+ typedef bool (*notify_notification_show_t)(void*, char*); -+ typedef void (*notify_notification_set_icon_from_pixbuf_t)(void*, GdkPixbuf*); -+ typedef void (*notify_notification_add_action_t)(void*, const char*, const char*, NotifyActionCallback, gpointer, GFreeFunc); -+ -+ nsCOMPtr mIconRequest; -+ nsCString mAlertTitle; -+ nsCString mAlertText; -+ -+ nsCOMPtr mAlertListener; -+ nsString mAlertCookie; -+ -+ bool mLoadedFrame; -+ bool mAlertHasAction; -+ -+ static void* libNotifyHandle; -+ static bool libNotifyNotAvail; -+ static notify_is_initted_t notify_is_initted; -+ static notify_init_t notify_init; -+ static notify_get_server_caps_t notify_get_server_caps; -+ static notify_notification_new_t notify_notification_new; -+ static notify_notification_show_t notify_notification_show; -+ static notify_notification_set_icon_from_pixbuf_t notify_notification_set_icon_from_pixbuf; -+ static notify_notification_add_action_t notify_notification_add_action; -+ NotifyNotification* mNotification; -+ gulong mClosureHandler; -+ -+ nsresult StartRequest(const nsAString & aImageUrl); -+ nsresult ShowAlert(GdkPixbuf* aPixbuf); -+}; -+ -+#endif -Index: thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsSystemAlertsService.cpp -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsSystemAlertsService.cpp 2014-11-03 19:19:05.000000000 +0000 -@@ -0,0 +1,57 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */ -+/* 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/. */ -+ -+#include "nsSystemAlertsService.h" -+#include "nsAlertsIconListener.h" -+#include "nsAutoPtr.h" -+ -+NS_IMPL_ADDREF(nsSystemAlertsService) -+NS_IMPL_RELEASE(nsSystemAlertsService) -+ -+NS_INTERFACE_MAP_BEGIN(nsSystemAlertsService) -+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertsService) -+ NS_INTERFACE_MAP_ENTRY(nsIAlertsService) -+NS_INTERFACE_MAP_END_THREADSAFE -+ -+nsSystemAlertsService::nsSystemAlertsService() -+{} -+ -+nsSystemAlertsService::~nsSystemAlertsService() -+{} -+ -+nsresult -+nsSystemAlertsService::Init() -+{ -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsSystemAlertsService::ShowAlertNotification(const nsAString & aImageUrl, -+ const nsAString & aAlertTitle, -+ const nsAString & aAlertText, -+ bool aAlertTextClickable, -+ const nsAString & aAlertCookie, -+ nsIObserver * aAlertListener, -+ const nsAString & aAlertName, -+ const nsAString & aBidi, -+ const nsAString & aLang, -+ const nsAString & aData, -+ nsIPrincipal * principal) -+{ -+ nsRefPtr alertListener = new nsAlertsIconListener(); -+ if (!alertListener) -+ return NS_ERROR_OUT_OF_MEMORY; -+ -+ return alertListener->InitAlertAsync(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, -+ aAlertCookie, aAlertListener); -+} -+ -+NS_IMETHODIMP -+nsSystemAlertsService::CloseAlert(const nsAString & aAlertName, -+ nsIPrincipal * principal) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -Index: thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsSystemAlertsService.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsSystemAlertsService.h 2014-11-03 19:19:05.000000000 +0000 -@@ -0,0 +1,26 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* 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/. */ -+ -+#ifndef nsSystemAlertsService_h__ -+#define nsSystemAlertsService_h__ -+ -+#include "nsIAlertsService.h" -+#include "nsCOMPtr.h" -+ -+class nsSystemAlertsService : public nsIAlertsService -+{ -+public: -+ NS_DECL_NSIALERTSSERVICE -+ NS_DECL_THREADSAFE_ISUPPORTS -+ -+ nsSystemAlertsService(); -+ -+ nsresult Init(); -+ -+private: -+ virtual ~nsSystemAlertsService(); -+}; -+ -+#endif /* nsSystemAlertsService_h__ */ -Index: thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/moz.build -=================================================================== ---- thunderbird-trunk-36.0~a1~hg20141101r16984.213438.orig/mozilla/toolkit/system/gnome/moz.build 2014-11-01 20:40:07.000000000 +0000 -+++ thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/moz.build 2014-11-03 19:19:05.000000000 +0000 -@@ -5,7 +5,9 @@ - # file, You can obtain one at http://mozilla.org/MPL/2.0/. - - SOURCES += [ -+ 'nsAlertsIconListener.cpp', - 'nsGnomeModule.cpp', -+ 'nsSystemAlertsService.cpp', - ] - - if CONFIG['MOZ_ENABLE_GCONF']: -Index: thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsGnomeModule.cpp -=================================================================== ---- thunderbird-trunk-36.0~a1~hg20141101r16984.213438.orig/mozilla/toolkit/system/gnome/nsGnomeModule.cpp 2014-11-01 20:40:07.000000000 +0000 -+++ thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsGnomeModule.cpp 2014-11-03 19:19:05.000000000 +0000 -@@ -22,6 +22,8 @@ - NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIOService) - NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGSettingsService, Init) - #endif -+#include "nsSystemAlertsService.h" -+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemAlertsService, Init) - - #ifdef MOZ_ENABLE_GCONF - NS_DEFINE_NAMED_CID(NS_GCONFSERVICE_CID); -@@ -33,6 +35,7 @@ - NS_DEFINE_NAMED_CID(NS_GIOSERVICE_CID); - NS_DEFINE_NAMED_CID(NS_GSETTINGSSERVICE_CID); - #endif -+NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID); - - static const mozilla::Module::CIDEntry kGnomeCIDs[] = { - #ifdef MOZ_ENABLE_GCONF -@@ -45,6 +48,7 @@ - { &kNS_GIOSERVICE_CID, false, nullptr, nsGIOServiceConstructor }, - { &kNS_GSETTINGSSERVICE_CID, false, nullptr, nsGSettingsServiceConstructor }, - #endif -+ { &kNS_SYSTEMALERTSSERVICE_CID, false, nullptr, nsSystemAlertsServiceConstructor }, - { nullptr } - }; - -@@ -59,6 +63,7 @@ - { NS_GIOSERVICE_CONTRACTID, &kNS_GIOSERVICE_CID }, - { NS_GSETTINGSSERVICE_CONTRACTID, &kNS_GSETTINGSSERVICE_CID }, - #endif -+ { NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_CID }, - { nullptr } - }; - -Index: thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsAlertsIconListener.cpp -=================================================================== ---- thunderbird-trunk-36.0~a1~hg20141101r16984.213438.orig/mozilla/toolkit/system/gnome/nsAlertsIconListener.cpp 2014-11-01 20:40:07.000000000 +0000 -+++ thunderbird-trunk-36.0~a1~hg20141101r16984.213438/mozilla/toolkit/system/gnome/nsAlertsIconListener.cpp 2014-11-03 19:18:21.338061869 +0000 -@@ -8,6 +8,7 @@ - #include "imgILoader.h" - #include "imgIRequest.h" - #include "nsNetUtil.h" -+#include "nsIContentPolicy.h" - #include "nsIImageToPixbuf.h" - #include "nsIStringBundle.h" - #include "nsIObserverService.h" -@@ -203,7 +204,8 @@ - - return il->LoadImageXPCOM(imageUri, nullptr, nullptr, nullptr, nullptr, - this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, -- nullptr, getter_AddRefs(mIconRequest)); -+ nsIContentPolicy::TYPE_IMAGE, -+ getter_AddRefs(mIconRequest)); - } - - void diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/series thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/series --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/series 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/series 2014-11-26 22:48:04.000000000 +0000 @@ -5,7 +5,6 @@ dont-override-general-useragent-locale.patch no_neon_on_arm.patch unity-menubar.patch -revert-removal-of-native-notifications.patch #test-integration/automation-output-junit-xml.patch #test-integration/xpcshell-output-valid-junit-xml.patch #test-fixes/mozmill-workaround-shebang-char-limit.patch @@ -17,3 +16,5 @@ #test-integration/xpcshell-dont-return-nonzero-on-test-failure.patch #test-fixes/xpcshell-chrome-fix-test_bug848297-with-locale-matchOS.patch #test-integration/xpcshell-write-time-for-failed-test.patch +support-coinstallable-trunk-build.patch +set-prgname-to-remoting-name.patch diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/set-prgname-to-remoting-name.patch thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/set-prgname-to-remoting-name.patch --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/set-prgname-to-remoting-name.patch 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/set-prgname-to-remoting-name.patch 2014-11-26 22:48:04.000000000 +0000 @@ -0,0 +1,19 @@ +Description: Ensure the WM class is set to the remoting name rather than + the application name, so that window matching works in the shell with + parallel installs +Author: Chris Coulson +Forwarded: no + +Index: firefox-trunk-36.0~a1~hg20141113r215607/mozilla/toolkit/xre/nsAppRunner.cpp +=================================================================== +--- firefox-trunk-36.0~a1~hg20141113r215607.orig/mozilla/toolkit/xre/nsAppRunner.cpp 2014-11-14 09:30:08.000000000 +0000 ++++ firefox-trunk-36.0~a1~hg20141113r215607/mozilla/toolkit/xre/nsAppRunner.cpp 2014-11-14 13:16:28.186684790 +0000 +@@ -3547,7 +3547,7 @@ + + // Set program name to the one defined in application.ini. + { +- nsAutoCString program(gAppData->name); ++ nsAutoCString program(gAppData->remotingName); + ToLowerCase(program); + g_set_prgname(program.get()); + } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/support-coinstallable-trunk-build.patch thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/support-coinstallable-trunk-build.patch --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/support-coinstallable-trunk-build.patch 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/support-coinstallable-trunk-build.patch 2014-11-26 22:48:04.000000000 +0000 @@ -0,0 +1,26 @@ +Description: Introduce --with-app-profile to change the profile location, so + that we can have nightly builds that are fully coinstallable with release + builds +Author: Chris Coulson +Forwarded: no + +Index: firefox-trunk-36.0~a1~hg20141113r215607/mozilla/configure.in +=================================================================== +--- firefox-trunk-36.0~a1~hg20141113r215607.orig/mozilla/configure.in 2014-11-14 13:36:25.000000000 +0000 ++++ firefox-trunk-36.0~a1~hg20141113r215607/mozilla/configure.in 2014-11-14 13:37:55.348948101 +0000 +@@ -4158,6 +4158,15 @@ + MOZ_APP_BASENAME="$WITH_APP_BASENAME" + fi + ++MOZ_ARG_WITH_STRING(app-profile, ++[--with-app-profile=APPPROFILE sets MOZ_APP_PROFILE to APPPROFILE], ++WITH_APP_PROFILE=$withval, ++) ++ ++if test -n "$WITH_APP_PROFILE" ; then ++ MOZ_APP_PROFILE="$WITH_APP_PROFILE" ++fi ++ + # Now is a good time to test for logic errors, define mismatches, etc. + case "$MOZ_BUILD_APP" in + xulrunner) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/unity-menubar.patch thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/unity-menubar.patch --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/patches/unity-menubar.patch 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/patches/unity-menubar.patch 2014-11-26 22:48:04.000000000 +0000 @@ -1,7 +1,7 @@ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/browser/base/content/browser-menubar.inc +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/browser/base/content/browser-menubar.inc =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/browser/base/content/browser-menubar.inc 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/browser/base/content/browser-menubar.inc 2014-11-01 00:15:08.057774885 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/browser/base/content/browser-menubar.inc 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/browser/base/content/browser-menubar.inc 2014-11-26 18:10:27.018413527 +0000 @@ -5,7 +5,11 @@ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/browser/components/places/content/places.xul +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/browser/components/places/content/places.xul =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/browser/components/places/content/places.xul 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/browser/components/places/content/places.xul 2014-11-01 00:15:08.057774885 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/browser/components/places/content/places.xul 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/browser/components/places/content/places.xul 2014-11-26 18:10:27.018413527 +0000 @@ -157,7 +157,7 @@ @@ -62,10 +62,10 @@ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/toolkit/content/xul.css +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/toolkit/content/xul.css =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/toolkit/content/xul.css 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/toolkit/content/xul.css 2014-11-01 00:15:08.057774885 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/toolkit/content/xul.css 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/toolkit/content/xul.css 2014-11-26 18:10:27.022413536 +0000 @@ -284,6 +284,18 @@ } %endif @@ -85,10 +85,10 @@ toolbarseparator { -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbardecoration"); } -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsDbusmenu.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsDbusmenu.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsDbusmenu.cpp 2014-11-01 00:15:08.057774885 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsDbusmenu.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -149,10 +149,10 @@ + + return NS_OK; +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsDbusmenu.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsDbusmenu.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsDbusmenu.h 2014-11-01 00:15:08.057774885 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsDbusmenu.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -253,10 +253,10 @@ +#define dbusmenu_menuitem_property_set_shortcut nsDbusmenuFunctions::s_dbusmenu_menuitem_property_set_shortcut + +#endif /* __nsDbusmenu_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenu.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenu.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenu.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenu.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,866 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -1124,10 +1124,10 @@ + + MaybeAddPlaceholderItem(); +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenu.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenu.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenu.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenu.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -1295,10 +1295,10 @@ +}; + +#endif /* __nsMenu_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuBar.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuBar.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuBar.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuBar.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,545 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -1845,10 +1845,10 @@ + DebugOnly rv = RemoveChild(aChild); + NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove item from menubar"); +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuBar.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuBar.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuBar.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuBar.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -1962,10 +1962,10 @@ +}; + +#endif /* __nsMenuBar_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuContainer.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuContainer.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuContainer.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuContainer.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -2146,10 +2146,10 @@ + + return aContent; +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuContainer.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuContainer.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuContainer.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuContainer.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -2217,10 +2217,10 @@ +}; + +#endif /* __nsMenuContainer_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuItem.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuItem.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuItem.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuItem.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,739 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -2961,10 +2961,10 @@ + UpdateIcon(sc); + } +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuItem.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuItem.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuItem.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuItem.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -3073,11 +3073,11 @@ +}; + +#endif /* __nsMenuItem_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuObject.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuObject.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuObject.cpp 2014-11-01 00:43:20.288619652 +0000 -@@ -0,0 +1,706 @@ ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuObject.cpp 2014-11-26 18:40:43.303065274 +0000 +@@ -0,0 +1,707 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: + */ @@ -3324,8 +3324,9 @@ + return; + } + -+ loader->LoadImage(uri, nullptr, nullptr, nullptr, loadGroup, this, -+ nullptr, nsIRequest::LOAD_NORMAL, nullptr, ++ loader->LoadImage(uri, nullptr, nullptr, mozilla::net::RP_Default, ++ nullptr, loadGroup, this, nullptr, ++ nsIRequest::LOAD_NORMAL, nullptr, + nsIContentPolicy::TYPE_IMAGE, EmptyString(), + getter_AddRefs(mImageRequest)); + } @@ -3784,10 +3785,10 @@ + weak = weak->GetPrevious(); + } +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuObject.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuObject.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuObject.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuObject.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,242 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4031,10 +4032,10 @@ +}; + +#endif /* __nsMenuObject_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuSeparator.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuSeparator.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuSeparator.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuSeparator.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4126,10 +4127,10 @@ + UpdateVisibility(sc); + } +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuSeparator.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuSeparator.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsMenuSeparator.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsMenuSeparator.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4172,10 +4173,10 @@ +}; + +#endif /* __nsMenuSeparator_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuAtomList.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuAtomList.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuAtomList.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuAtomList.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,11 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4188,10 +4189,10 @@ +WIDGET_ATOM2(_moz_menupopupstate, "_moz-menupopupstate") +WIDGET_ATOM(openedwithkey) +WIDGET_ATOM(shellshowingmenubar) -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuAtoms.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuAtoms.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuAtoms.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuAtoms.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4232,10 +4233,10 @@ +{ + NS_RegisterStaticAtoms(gAtoms); +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuAtoms.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuAtoms.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuAtoms.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuAtoms.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4262,10 +4263,10 @@ +}; + +#endif /* __nsNativeMenuAtoms_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuDocListener.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuDocListener.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuDocListener.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuDocListener.cpp 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,369 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4636,10 +4637,10 @@ + CancelFlush(this); + mPendingMutations.Clear(); +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuDocListener.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuDocListener.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuDocListener.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuDocListener.h 2014-11-26 18:10:27.022413536 +0000 @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -4793,10 +4794,10 @@ +}; + +#endif /* __nsNativeMenuDocListener_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuService.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuService.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuService.cpp 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuService.cpp 2014-11-26 18:10:27.026413546 +0000 @@ -0,0 +1,506 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -5304,10 +5305,10 @@ + + return NS_OK; +} -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuService.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuService.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuService.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuService.h 2014-11-26 18:10:27.026413546 +0000 @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -5397,10 +5398,10 @@ +}; + +#endif /* __nsNativeMenuService_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuUtils.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuUtils.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsNativeMenuUtils.h 2014-11-01 00:15:08.061774893 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsNativeMenuUtils.h 2014-11-26 18:10:27.026413546 +0000 @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: @@ -5461,10 +5462,10 @@ +}; + +#endif /* __nsNativeMenuUtils_h__ */ -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsWidgetFactory.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsWidgetFactory.cpp =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/widget/gtk/nsWidgetFactory.cpp 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsWidgetFactory.cpp 2014-11-01 00:15:08.061774893 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/widget/gtk/nsWidgetFactory.cpp 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsWidgetFactory.cpp 2014-11-26 18:10:27.026413546 +0000 @@ -44,6 +44,9 @@ #include "GfxInfoX11.h" #endif @@ -5533,11 +5534,11 @@ nsWidgetGtk2ModuleDtor }; -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsWindow.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsWindow.cpp =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/widget/gtk/nsWindow.cpp 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsWindow.cpp 2014-11-01 00:15:08.061774893 +0000 -@@ -4777,6 +4777,11 @@ +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/widget/gtk/nsWindow.cpp 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsWindow.cpp 2014-11-26 18:10:27.026413546 +0000 +@@ -4778,6 +4778,11 @@ return NS_OK; } @@ -5549,10 +5550,10 @@ bool nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel, bool aAlwaysRollup) -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsWindow.h +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsWindow.h =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/widget/gtk/nsWindow.h 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/nsWindow.h 2014-11-01 00:15:08.061774893 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/widget/gtk/nsWindow.h 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/nsWindow.h 2014-11-26 18:10:27.026413546 +0000 @@ -34,6 +34,8 @@ #include "nsGtkIMModule.h" @@ -5562,8 +5563,8 @@ #undef LOG #ifdef MOZ_LOGGING -@@ -148,6 +150,8 @@ - NS_IMETHOD MakeFullScreen(bool aFullScreen); +@@ -149,6 +151,8 @@ + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr); NS_IMETHOD HideWindowChrome(bool aShouldHide); + void SetMenuBar(nsMenuBar *aMenuBar); @@ -5571,7 +5572,7 @@ /** * GetLastUserInputTime returns a timestamp for the most recent user input * event. This is intended for pointer grab requests (including drags). -@@ -467,6 +471,8 @@ +@@ -473,6 +477,8 @@ * however, IME doesn't work at that time. */ nsRefPtr mIMModule; @@ -5580,10 +5581,10 @@ }; class nsChildWindow : public nsWindow { -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/xpfe/appshell/nsWebShellWindow.cpp +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/xpfe/appshell/nsWebShellWindow.cpp =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/xpfe/appshell/nsWebShellWindow.cpp 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/xpfe/appshell/nsWebShellWindow.cpp 2014-11-01 00:15:08.061774893 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/xpfe/appshell/nsWebShellWindow.cpp 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/xpfe/appshell/nsWebShellWindow.cpp 2014-11-26 18:10:27.026413546 +0000 @@ -58,6 +58,7 @@ #include "nsIScreen.h" @@ -5616,10 +5617,10 @@ if (nms && menubarContent) nms->CreateNativeMenuBar(aParentWindow, menubarContent); } -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/moz.build +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/moz.build =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/widget/gtk/moz.build 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/gtk/moz.build 2014-11-01 00:15:08.065774901 +0000 +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/widget/gtk/moz.build 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/gtk/moz.build 2014-11-26 18:10:27.026413546 +0000 @@ -19,11 +19,20 @@ 'nsAppShell.cpp', 'nsBidiKeyboard.cpp', @@ -5657,11 +5658,11 @@ '/layout/xul', '/other-licenses/atk-1.0', '/widget', -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/browser/base/content/browser.js +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/browser/base/content/browser.js =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/browser/base/content/browser.js 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/browser/base/content/browser.js 2014-11-01 00:15:08.065774901 +0000 -@@ -4475,6 +4475,8 @@ +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/browser/base/content/browser.js 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/browser/base/content/browser.js 2014-11-26 18:10:27.026413546 +0000 +@@ -4660,6 +4660,8 @@ let toolbarNodes = Array.slice(gNavToolbox.childNodes); toolbarNodes = toolbarNodes.concat(gNavToolbox.externalToolbars); toolbarNodes = toolbarNodes.filter(node => node.getAttribute("toolbarname")); @@ -5670,11 +5671,11 @@ return toolbarNodes; } -Index: firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/moz.build +Index: firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/moz.build =================================================================== ---- firefox-trunk-36.0~a1~hg20141031r213433.orig/mozilla/widget/moz.build 2014-11-01 00:15:08.065774901 +0000 -+++ firefox-trunk-36.0~a1~hg20141031r213433/mozilla/widget/moz.build 2014-11-01 00:15:08.065774901 +0000 -@@ -36,10 +36,12 @@ +--- firefox-trunk-36.0~a1~hg20141125r217359.orig/mozilla/widget/moz.build 2014-11-26 18:10:27.030413557 +0000 ++++ firefox-trunk-36.0~a1~hg20141125r217359/mozilla/widget/moz.build 2014-11-26 18:10:27.026413546 +0000 +@@ -37,10 +37,12 @@ 'nsITaskbarProgress.idl', ] EXPORTS += [ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/rules thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/rules --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/rules 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/rules 2014-11-26 22:48:04.000000000 +0000 @@ -118,30 +118,6 @@ pre-build:: $(shell /usr/bin/docbook-to-man $(CURDIR)/debian/thunderbird.sgml > $(CURDIR)/debian/$(MOZ_APP_NAME).1) -monkey-patch-upstream-files:: -ifneq ($(MOZ_APP_BASENAME),$(MOZ_DEFAULT_APP_BASENAME)) - @echo "Changing Name in application.ini to $(MOZ_APP_BASENAME)" - $(call moz_monkey_patch_file,$(DEB_SRCDIR)/mail/app/application.ini, \ - sed -i 's/^\(Name\=\).*/\1$(MOZ_APP_BASENAME)/') - @echo "Setting MOZ_APP_UA_NAME to $(MOZ_DEFAULT_APP_BASENAME)" - $(call moz_monkey_patch_file,$(DEB_SRCDIR)/mail/confvars.sh, \ - echo "MOZ_APP_UA_NAME=$(MOZ_DEFAULT_APP_BASENAME)" >>) - @echo "Setting MOZ_APP_BASENAME to $(MOZ_APP_BASENAME)" - $(call moz_monkey_patch_file,$(DEB_SRCDIR)/mail/confvars.sh, \ - sed -i 's/^\(MOZ_APP_BASENAME\=\).*/\1$(MOZ_APP_BASENAME)/') -endif -ifneq ($(MOZ_APP_NAME),$(MOZ_DEFAULT_APP_NAME)) - @echo "Setting MOZ_APP_NAME to $(MOZ_APP_NAME)" - $(call moz_monkey_patch_file,$(DEB_SRCDIR)/mail/confvars.sh, \ - sed -i 's/^\(MOZ_APP_NAME\=\).*/\1$(MOZ_APP_NAME)/') - @echo "Replacing instances of \"%APP%\" with \"thunderbird\" in mail/app/profile/all-thunderbird.js" - $(call moz_monkey_patch_file,mail/app/profile/all-thunderbird.js, \ - sed -ri 's/%APP%/thunderbird/g') - @echo "Replacing instances of \"%APP%\" with \"thunderbird\" in $(MOZ_BRANDING_DIR)/thunderbird-branding.js" - $(call moz_monkey_patch_file,$(MOZ_BRANDING_DIR)/thunderbird-branding.js, \ - sed -ri 's/%APP%/thunderbird/g') -endif - clean:: rm -f debian/messagingmenu/*.xpi rm -f debian/eds/*.xpi diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/thunderbird.sh.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/thunderbird.sh.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/debian/thunderbird.sh.in 2014-11-14 10:11:42.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/debian/thunderbird.sh.in 2014-11-26 22:48:04.000000000 +0000 @@ -16,8 +16,6 @@ MOZ_APP_LAUNCHER=`which $0` EXE=@MOZ_APP_NAME@ MOZ_APP_NAME=@MOZ_APP_NAME@ -MOZ_DEFAULT_PROFILEDIR=@MOZ_DEFAULT_PROFILEDIR@ -MOZ_PROFILEDIR=@MOZ_PROFILEDIR@ export MOZ_APP_LAUNCHER @@ -81,14 +79,6 @@ esac done -%%if MOZ_PROFILEDIR != MOZ_DEFAULT_PROFILEDIR -if [ $MOZ_PROFILEDIR != $MOZ_DEFAULT_PROFILEDIR ] && - [ ! -e ${HOME}/${MOZ_PROFILEDIR} ] && - [ -d ${HOME}/${MOZ_DEFAULT_PROFILEDIR} ] ; then - cp -r ${HOME}/${MOZ_DEFAULT_PROFILEDIR} ${HOME}/${MOZ_PROFILEDIR} -fi -%%endif - if [ $moz_debug -eq 1 ] ; then case $moz_debugger in memcheck) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/editor/ui/dialogs/content/EdReplace.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/editor/ui/dialogs/content/EdReplace.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/editor/ui/dialogs/content/EdReplace.xul 2014-11-14 09:36:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/editor/ui/dialogs/content/EdReplace.xul 2014-11-26 21:44:59.000000000 +0000 @@ -14,7 +14,7 @@ persist="screenX screenY" buttons="cancel" onload = "onLoad()" - ondialogaccept="return onFindNext();"> + ondialogaccept="onFindNext(); return false"> + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/textattrs/test_general.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/textattrs/test_general.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/textattrs/test_general.html 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/textattrs/test_general.html 2014-11-26 21:45:45.000000000 +0000 @@ -709,12 +709,12 @@

- underline - blue - dotted - linethrough - blue - wavy + underline + blue + dotted + linethrough + blue + wavy

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/tree/test_aria_list.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/tree/test_aria_list.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/tree/test_aria_list.html 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/tree/test_aria_list.html 2014-11-26 21:45:45.000000000 +0000 @@ -34,10 +34,15 @@ accTree = { // div@role="list" role: ROLE_LIST, children: [ - { // li text leaf - role: ROLE_TEXT_LEAF, - name: "item1", - children: [ ] + { // li + role: ROLE_PARAGRAPH, + children: [ + { // li text leaf + role: ROLE_TEXT_LEAF, + name: "item1", + children: [ ] + } + ] }, { // li@role="listitem" role: ROLE_LISTITEM, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/tree/test_aria_presentation.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/tree/test_aria_presentation.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/tree/test_aria_presentation.html 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/tree/test_aria_presentation.html 2014-11-26 21:45:45.000000000 +0000 @@ -56,6 +56,15 @@ ] }; testAccessibleTree("tblfocusable_cnt", tree); + // Presentation list, expose generic accesisble for list items. + tree = + { SECTION: [ // container + { PARAGRAPH: [ // li generic accessible + { TEXT_LEAF: [ ] } // li text + ] } + ] }; + testAccessibleTree("list_cnt", tree); + // Has ARIA globals or referred by ARIA relationship. tree = { SECTION: [ // container @@ -113,6 +122,12 @@ +
+
    +
  • item
  • +
+
+
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/tree/test_brokencontext.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/tree/test_brokencontext.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/accessible/tests/mochitest/tree/test_brokencontext.html 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/accessible/tests/mochitest/tree/test_brokencontext.html 2014-11-26 21:45:45.000000000 +0000 @@ -80,15 +80,15 @@ ok(!isAccessible("presentation_ul"), "presentational ul shouldn't be accessible"); - ok(!isAccessible("item_in_presentation_ul"), - "li in presentational ul shouldn't be accessible"); - ok(!isAccessible("styleditem_in_presentation_ul"), - "list styled span in presentational ul shouldn't be accessible"); + ok(isAccessible("item_in_presentation_ul"), + "li in presentational ul should have generic accessible"); + ok(isAccessible("styleditem_in_presentation_ul"), + "list styled span in presentational ul should have generic accessible"); ok(!isAccessible("presentation_ol"), "presentational ol shouldn't be accessible"); - ok(!isAccessible("item_in_presentation_ol"), - "li in presentational ol shouldn't be accessible"); + ok(isAccessible("item_in_presentation_ol"), + "li in presentational ol should have generic accessible"); ok(!isAccessible("presentation_dl"), "presentational dl shouldn't be accessible"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/moz.build 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/moz.build 2014-11-26 21:45:45.000000000 +0000 @@ -171,6 +171,7 @@ ] EXTRA_JS_MODULES.commonjs.framescript += [ + 'source/lib/framescript/contextmenu-events.js', 'source/lib/framescript/FrameScriptManager.jsm', 'source/lib/framescript/LoaderHelper.jsm', 'source/lib/framescript/tab-events.js', @@ -235,6 +236,7 @@ EXTRA_JS_MODULES.commonjs.sdk.content += [ 'source/lib/sdk/content/content-worker.js', 'source/lib/sdk/content/content.js', + 'source/lib/sdk/content/context-menu.js', 'source/lib/sdk/content/events.js', 'source/lib/sdk/content/loader.js', 'source/lib/sdk/content/mod.js', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/framescript/contextmenu-events.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/framescript/contextmenu-events.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/framescript/contextmenu-events.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/framescript/contextmenu-events.js 2014-11-26 21:45:45.000000000 +0000 @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +const { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); + +// Holds remote items for this frame. +let keepAlive = new Map(); + +// Called to create remote proxies for items. If they already exist we destroy +// and recreate. This cna happen if the item changes in some way or in odd +// timing cases where the frame script is create around the same time as the +// item is created in the main process +addMessageListener('sdk/contextmenu/createitems', ({ data: { items, addon }}) => { + let { loader } = Cu.import(addon.paths[''] + 'framescript/LoaderHelper.jsm', {}); + + for (let itemoptions of items) { + let { RemoteItem } = loader(addon).require('sdk/content/context-menu'); + let item = new RemoteItem(itemoptions, this); + + let oldItem = keepAlive.get(item.id); + if (oldItem) { + oldItem.destroy(); + } + + keepAlive.set(item.id, item); + } +}); + +addMessageListener('sdk/contextmenu/destroyitems', ({ data: { items }}) => { + for (let id of items) { + let item = keepAlive.get(id); + item.destroy(); + keepAlive.delete(id); + } +}); + +sendAsyncMessage('sdk/contextmenu/requestitems'); + +Services.obs.addObserver(function(subject, topic, data) { + // Many frame scripts run in the same process, check that the context menu + // node is in this frame + let { event: { target: popupNode }, addonInfo } = subject.wrappedJSObject; + if (popupNode.ownerDocument.defaultView.top != content) + return; + + for (let item of keepAlive.values()) { + item.getContextState(popupNode, addonInfo); + } +}, "content-contextmenu", false); + +addMessageListener('sdk/contextmenu/activateitems', ({ data: { items, data }, objects: { popupNode }}) => { + for (let id of items) { + let item = keepAlive.get(id); + if (!item) + continue; + + item.activate(popupNode, data); + } +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/framescript/FrameScriptManager.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/framescript/FrameScriptManager.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/framescript/FrameScriptManager.jsm 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/framescript/FrameScriptManager.jsm 2014-11-26 21:45:45.000000000 +0000 @@ -15,11 +15,21 @@ let loadedTabEvents = false; function enableTabEvents() { - if (loadedTabEvents) + if (loadedTabEvents) return; loadedTabEvents = true; globalMM.loadFrameScript(PATH + 'tab-events.js', true); } -const EXPORTED_SYMBOLS = ['enableTabEvents']; +let loadedCMEvents = false; + +function enableCMEvents() { + if (loadedCMEvents) + return; + + loadedCMEvents = true; + globalMM.loadFrameScript(PATH + 'contextmenu-events.js', true); +} + +const EXPORTED_SYMBOLS = ['enableTabEvents', 'enableCMEvents']; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/sdk/content/context-menu.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/sdk/content/context-menu.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/sdk/content/context-menu.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/sdk/content/context-menu.js 2014-11-26 21:45:45.000000000 +0000 @@ -0,0 +1,354 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Class } = require("../core/heritage"); +const self = require("../self"); +const { WorkerChild } = require("./worker-child"); +const { getInnerId } = require("../window/utils"); +const { Ci } = require("chrome"); +const { Services } = require("resource://gre/modules/Services.jsm"); + +// These functions are roughly copied from sdk/selection which doesn't work +// in the content process +function getElementWithSelection(window) { + let element = Services.focus.getFocusedElementForWindow(window, false, {}); + if (!element) + return null; + + try { + // Accessing selectionStart and selectionEnd on e.g. a button + // results in an exception thrown as per the HTML5 spec. See + // http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#textFieldSelection + + let { value, selectionStart, selectionEnd } = element; + + let hasSelection = typeof value === "string" && + !isNaN(selectionStart) && + !isNaN(selectionEnd) && + selectionStart !== selectionEnd; + + return hasSelection ? element : null; + } + catch (err) { + console.exception(err); + return null; + } +} + +function safeGetRange(selection, rangeNumber) { + try { + let { rangeCount } = selection; + let range = null; + + for (let rangeNumber = 0; rangeNumber < rangeCount; rangeNumber++ ) { + range = selection.getRangeAt(rangeNumber); + + if (range && range.toString()) + break; + + range = null; + } + + return range; + } + catch (e) { + return null; + } +} + +function getSelection(window) { + let selection = window.getSelection(); + let range = safeGetRange(selection); + if (range) + return range.toString(); + + let node = getElementWithSelection(window); + if (!node) + return null; + + return node.value.substring(node.selectionStart, node.selectionEnd); +} + +//These are used by PageContext.isCurrent below. If the popupNode or any of +//its ancestors is one of these, Firefox uses a tailored context menu, and so +//the page context doesn't apply. +const NON_PAGE_CONTEXT_ELTS = [ + Ci.nsIDOMHTMLAnchorElement, + Ci.nsIDOMHTMLAppletElement, + Ci.nsIDOMHTMLAreaElement, + Ci.nsIDOMHTMLButtonElement, + Ci.nsIDOMHTMLCanvasElement, + Ci.nsIDOMHTMLEmbedElement, + Ci.nsIDOMHTMLImageElement, + Ci.nsIDOMHTMLInputElement, + Ci.nsIDOMHTMLMapElement, + Ci.nsIDOMHTMLMediaElement, + Ci.nsIDOMHTMLMenuElement, + Ci.nsIDOMHTMLObjectElement, + Ci.nsIDOMHTMLOptionElement, + Ci.nsIDOMHTMLSelectElement, + Ci.nsIDOMHTMLTextAreaElement, +]; + +// List all editable types of inputs. Or is it better to have a list +// of non-editable inputs? +let editableInputs = { + email: true, + number: true, + password: true, + search: true, + tel: true, + text: true, + textarea: true, + url: true +}; + +let CONTEXTS = {}; + +let Context = Class({ + initialize: function(id) { + this.id = id; + }, + + adjustPopupNode: function adjustPopupNode(popupNode) { + return popupNode; + }, + + // Gets state to pass through to the parent process for the node the user + // clicked on + getState: function(popupNode) { + return false; + } +}); + +// Matches when the context-clicked node doesn't have any of +// NON_PAGE_CONTEXT_ELTS in its ancestors +CONTEXTS.PageContext = Class({ + extends: Context, + + getState: function(popupNode) { + // If there is a selection in the window then this context does not match + if (!popupNode.ownerDocument.defaultView.getSelection().isCollapsed) + return false; + + // If the clicked node or any of its ancestors is one of the blacklisted + // NON_PAGE_CONTEXT_ELTS then this context does not match + while (!(popupNode instanceof Ci.nsIDOMDocument)) { + if (NON_PAGE_CONTEXT_ELTS.some(function(type) popupNode instanceof type)) + return false; + + popupNode = popupNode.parentNode; + } + + return true; + } +}); + +// Matches when there is an active selection in the window +CONTEXTS.SelectionContext = Class({ + extends: Context, + + getState: function(popupNode) { + if (!popupNode.ownerDocument.defaultView.getSelection().isCollapsed) + return true; + + try { + // The node may be a text box which has selectionStart and selectionEnd + // properties. If not this will throw. + let { selectionStart, selectionEnd } = popupNode; + return !isNaN(selectionStart) && !isNaN(selectionEnd) && + selectionStart !== selectionEnd; + } + catch (e) { + return false; + } + } +}); + +// Matches when the context-clicked node or any of its ancestors matches the +// selector given +CONTEXTS.SelectorContext = Class({ + extends: Context, + + initialize: function initialize(id, selector) { + Context.prototype.initialize.call(this, id); + this.selector = selector; + }, + + adjustPopupNode: function adjustPopupNode(popupNode) { + let selector = this.selector; + + while (!(popupNode instanceof Ci.nsIDOMDocument)) { + if (popupNode.mozMatchesSelector(selector)) + return popupNode; + + popupNode = popupNode.parentNode; + } + + return null; + }, + + getState: function(popupNode) { + return !!this.adjustPopupNode(popupNode); + } +}); + +// Matches when the page url matches any of the patterns given +CONTEXTS.URLContext = Class({ + extends: Context, + + getState: function(popupNode) { + return popupNode.ownerDocument.URL; + } +}); + +// Matches when the user-supplied predicate returns true +CONTEXTS.PredicateContext = Class({ + extends: Context, + + getState: function(node) { + let window = node.ownerDocument.defaultView; + let data = {}; + + data.documentType = node.ownerDocument.contentType; + + data.documentURL = node.ownerDocument.location.href; + data.targetName = node.nodeName.toLowerCase(); + data.targetID = node.id || null ; + + if ((data.targetName === 'input' && editableInputs[node.type]) || + data.targetName === 'textarea') { + data.isEditable = !node.readOnly && !node.disabled; + } + else { + data.isEditable = node.isContentEditable; + } + + data.selectionText = getSelection(window, "TEXT"); + + data.srcURL = node.src || null; + data.value = node.value || null; + + while (!data.linkURL && node) { + data.linkURL = node.href || null; + node = node.parentNode; + } + + return data; + }, +}); + +function instantiateContext({ id, type, args }) { + if (!(type in CONTEXTS)) { + console.error("Attempt to use unknown context " + type); + return; + } + return new CONTEXTS[type](id, ...args); +} + +let ContextWorker = Class({ + implements: [ WorkerChild ], + + // Calls the context workers context listeners and returns the first result + // that is either a string or a value that evaluates to true. If all of the + // listeners returned false then returns false. If there are no listeners, + // returns true (show the menu item by default). + getMatchedContext: function getCurrentContexts(popupNode) { + let results = this.sandbox.emitSync("context", popupNode); + if (!results.length) + return true; + return results.reduce((val, result) => val || result); + }, + + // Emits a click event in the worker's port. popupNode is the node that was + // context-clicked, and clickedItemData is the data of the item that was + // clicked. + fireClick: function fireClick(popupNode, clickedItemData) { + this.sandbox.emitSync("click", popupNode, clickedItemData); + } +}); + +// Gets the item's content script worker for a window, creating one if necessary +// Once created it will be automatically destroyed when the window unloads. +// If there is not content scripts for the item then null will be returned. +function getItemWorkerForWindow(item, window) { + if (!item.contentScript && !item.contentScriptFile) + return null; + + let id = getInnerId(window); + let worker = item.workerMap.get(id); + + if (worker) + return worker; + + worker = ContextWorker({ + id: item.id, + window: id, + manager: item.manager, + contentScript: item.contentScript, + contentScriptFile: item.contentScriptFile, + onDetach: function() { + item.workerMap.delete(id); + } + }); + + item.workerMap.set(id, worker); + + return worker; +} + +// A very simple remote proxy for every item. It's job is to provide data for +// the main process to use to determine visibility state and to call into +// content scripts when clicked. +let RemoteItem = Class({ + initialize: function(options, manager) { + this.id = options.id; + this.contexts = [instantiateContext(c) for (c of options.contexts)]; + this.contentScript = options.contentScript; + this.contentScriptFile = options.contentScriptFile; + + this.manager = manager; + + this.workerMap = new Map(); + }, + + destroy: function() { + for (let worker of this.workerMap.values()) { + worker.destroy(); + } + }, + + activate: function(popupNode, data) { + let worker = getItemWorkerForWindow(this, popupNode.ownerDocument.defaultView); + if (!worker) + return; + + for (let context of this.contexts) + popupNode = context.adjustPopupNode(popupNode); + + worker.fireClick(popupNode, data); + }, + + // Fills addonInfo with state data to send through to the main process + getContextState: function(popupNode, addonInfo) { + if (!(self.id in addonInfo)) + addonInfo[self.id] = {}; + + let worker = getItemWorkerForWindow(this, popupNode.ownerDocument.defaultView); + let contextStates = {}; + for (let context of this.contexts) + contextStates[context.id] = context.getState(popupNode); + + addonInfo[self.id][this.id] = { + // It isn't ideal to create a PageContext for every item but there isn't + // a good shared place to do it. + pageContext: (new CONTEXTS.PageContext()).getState(popupNode), + contextStates, + hasWorker: !!worker, + workerContext: worker ? worker.getMatchedContext(popupNode) : true + } + } +}); +exports.RemoteItem = RemoteItem; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/sdk/context-menu.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/sdk/context-menu.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/lib/sdk/context-menu.js 2014-11-14 09:37:10.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/lib/sdk/context-menu.js 2014-11-26 21:45:45.000000000 +0000 @@ -19,14 +19,20 @@ const { URL, isValidURI } = require("./url"); const { WindowTracker, browserWindowIterator } = require("./deprecated/window-utils"); const { isBrowser, getInnerId } = require("./window/utils"); -const { Ci } = require("chrome"); +const { Ci, Cc, Cu } = require("chrome"); const { MatchPattern } = require("./util/match-pattern"); const { Worker } = require("./content/worker"); const { EventTarget } = require("./event/target"); const { emit } = require('./event/core'); const { when } = require('./system/unload'); -const selection = require('./selection'); const { contract: loaderContract } = require('./content/loader'); +const { omit } = require('./util/object'); +const self = require('./self') + +// null-out cycles in .modules to make @loader/options JSONable +const ADDON = omit(require('@loader/options'), ['modules', 'globals']); + +require('../framescript/FrameScriptManager.jsm').enableCMEvents(); // All user items we add have this class. const ITEM_CLASS = "addon-context-menu-item"; @@ -59,30 +65,13 @@ // The class of the overflow submenu's xul:menupopup. const OVERFLOW_POPUP_CLASS = "addon-content-menu-overflow-popup"; -//These are used by PageContext.isCurrent below. If the popupNode or any of -//its ancestors is one of these, Firefox uses a tailored context menu, and so -//the page context doesn't apply. -const NON_PAGE_CONTEXT_ELTS = [ - Ci.nsIDOMHTMLAnchorElement, - Ci.nsIDOMHTMLAppletElement, - Ci.nsIDOMHTMLAreaElement, - Ci.nsIDOMHTMLButtonElement, - Ci.nsIDOMHTMLCanvasElement, - Ci.nsIDOMHTMLEmbedElement, - Ci.nsIDOMHTMLImageElement, - Ci.nsIDOMHTMLInputElement, - Ci.nsIDOMHTMLMapElement, - Ci.nsIDOMHTMLMediaElement, - Ci.nsIDOMHTMLMenuElement, - Ci.nsIDOMHTMLObjectElement, - Ci.nsIDOMHTMLOptionElement, - Ci.nsIDOMHTMLSelectElement, - Ci.nsIDOMHTMLTextAreaElement, -]; - // Holds private properties for API objects let internal = ns(); +function uuid() { + return require('./util/uuid').uuid().toString(); +} + function getScheme(spec) { try { return URL(spec).scheme; @@ -92,15 +81,22 @@ } } +let MessageManager = Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIMessageBroadcaster); + let Context = Class({ + initialize: function() { + internal(this).id = uuid(); + }, + // Returns the node that made this context current adjustPopupNode: function adjustPopupNode(popupNode) { return popupNode; }, // Returns whether this context is current for the current node - isCurrent: function isCurrent(popupNode) { - return false; + isCurrent: function isCurrent(state) { + return state; } }); @@ -109,21 +105,12 @@ let PageContext = Class({ extends: Context, - isCurrent: function isCurrent(popupNode) { - // If there is a selection in the window then this context does not match - if (!popupNode.ownerDocument.defaultView.getSelection().isCollapsed) - return false; - - // If the clicked node or any of its ancestors is one of the blacklisted - // NON_PAGE_CONTEXT_ELTS then this context does not match - while (!(popupNode instanceof Ci.nsIDOMDocument)) { - if (NON_PAGE_CONTEXT_ELTS.some(function(type) popupNode instanceof type)) - return false; - - popupNode = popupNode.parentNode; + serialize: function() { + return { + id: internal(this).id, + type: "PageContext", + args: [] } - - return true; } }); exports.PageContext = PageContext; @@ -132,19 +119,11 @@ let SelectionContext = Class({ extends: Context, - isCurrent: function isCurrent(popupNode) { - if (!popupNode.ownerDocument.defaultView.getSelection().isCollapsed) - return true; - - try { - // The node may be a text box which has selectionStart and selectionEnd - // properties. If not this will throw. - let { selectionStart, selectionEnd } = popupNode; - return !isNaN(selectionStart) && !isNaN(selectionEnd) && - selectionStart !== selectionEnd; - } - catch (e) { - return false; + serialize: function() { + return { + id: internal(this).id, + type: "SelectionContext", + args: [] } } }); @@ -156,6 +135,7 @@ extends: Context, initialize: function initialize(selector) { + Context.prototype.initialize.call(this); let options = validateOptions({ selector: selector }, { selector: { is: ["string"], @@ -165,21 +145,12 @@ internal(this).selector = options.selector; }, - adjustPopupNode: function adjustPopupNode(popupNode) { - let selector = internal(this).selector; - - while (!(popupNode instanceof Ci.nsIDOMDocument)) { - if (popupNode.mozMatchesSelector(selector)) - return popupNode; - - popupNode = popupNode.parentNode; + serialize: function() { + return { + id: internal(this).id, + type: "SelectorContext", + args: [internal(this).selector] } - - return null; - }, - - isCurrent: function isCurrent(popupNode) { - return !!this.adjustPopupNode(popupNode); } }); exports.SelectorContext = SelectorContext; @@ -189,6 +160,7 @@ extends: Context, initialize: function initialize(patterns) { + Context.prototype.initialize.call(this); patterns = Array.isArray(patterns) ? patterns : [patterns]; try { @@ -198,12 +170,18 @@ throw new Error("Patterns must be a string, regexp or an array of " + "strings or regexps: " + err); } - }, - isCurrent: function isCurrent(popupNode) { - let url = popupNode.ownerDocument.URL; + isCurrent: function isCurrent(url) { return internal(this).patterns.some(function (p) p.test(url)); + }, + + serialize: function() { + return { + id: internal(this).id, + type: "URLContext", + args: [] + } } }); exports.URLContext = URLContext; @@ -213,6 +191,7 @@ extends: Context, initialize: function initialize(predicate) { + Context.prototype.initialize.call(this); let options = validateOptions({ predicate: predicate }, { predicate: { is: ["function"], @@ -222,56 +201,20 @@ internal(this).predicate = options.predicate; }, - isCurrent: function isCurrent(popupNode) { - return internal(this).predicate(populateCallbackNodeData(popupNode)); + isCurrent: function isCurrent(state) { + return internal(this).predicate(state); + }, + + serialize: function() { + return { + id: internal(this).id, + type: "PredicateContext", + args: [] + } } }); exports.PredicateContext = PredicateContext; -// List all editable types of inputs. Or is it better to have a list -// of non-editable inputs? -let editableInputs = { - email: true, - number: true, - password: true, - search: true, - tel: true, - text: true, - textarea: true, - url: true -}; - -function populateCallbackNodeData(node) { - let window = node.ownerDocument.defaultView; - let data = {}; - - data.documentType = node.ownerDocument.contentType; - - data.documentURL = node.ownerDocument.location.href; - data.targetName = node.nodeName.toLowerCase(); - data.targetID = node.id || null ; - - if ((data.targetName === 'input' && editableInputs[node.type]) || - data.targetName === 'textarea') { - data.isEditable = !node.readOnly && !node.disabled; - } - else { - data.isEditable = node.isContentEditable; - } - - data.selectionText = selection.text; - - data.srcURL = node.src || null; - data.value = node.value || null; - - while (!data.linkURL && node) { - data.linkURL = node.href || null; - node = node.parentNode; - } - - return data; -} - function removeItemFromArray(array, item) { return array.filter(function(i) i !== item); } @@ -362,130 +305,82 @@ } }); -let ContextWorker = Class({ - implements: [ Worker ], - - // Calls the context workers context listeners and returns the first result - // that is either a string or a value that evaluates to true. If all of the - // listeners returned false then returns false. If there are no listeners, - // returns true (show the menu item by default). - getMatchedContext: function getCurrentContexts(popupNode) { - let results = this.getSandbox().emitSync("context", popupNode); - if (!results.length) - return true; - return results.reduce((val, result) => val || result); - }, - - // Emits a click event in the worker's port. popupNode is the node that was - // context-clicked, and clickedItemData is the data of the item that was - // clicked. - fireClick: function fireClick(popupNode, clickedItemData) { - this.getSandbox().emitSync("click", popupNode, clickedItemData); - } -}); - // Returns true if any contexts match. If there are no contexts then a // PageContext is tested instead -function hasMatchingContext(contexts, popupNode) { - for (let context in contexts) { - if (!context.isCurrent(popupNode)) +function hasMatchingContext(contexts, addonInfo) { + for (let context of contexts) { + if (!(internal(context).id in addonInfo.contextStates)) { + console.error("Missing state for context " + internal(context).id + " this is an error in the SDK modules."); + return false; + } + if (!context.isCurrent(addonInfo.contextStates[internal(context).id])) return false; } return true; } -// Gets the matched context from any worker for this item. If there is no worker -// or no matched context then returns false. -function getCurrentWorkerContext(item, popupNode) { - let worker = getItemWorkerForWindow(item, popupNode.ownerDocument.defaultView); - if (!worker) - return true; - return worker.getMatchedContext(popupNode); -} - // Tests whether an item should be visible or not based on its contexts and // content scripts -function isItemVisible(item, popupNode, defaultVisibility) { +function isItemVisible(item, addonInfo, usePageWorker) { if (!item.context.length) { - let worker = getItemWorkerForWindow(item, popupNode.ownerDocument.defaultView); - if (!worker) - return defaultVisibility; + if (!addonInfo.hasWorker) + return usePageWorker ? addonInfo.pageContext : true; } - if (!hasMatchingContext(item.context, popupNode)) + if (!hasMatchingContext(item.context, addonInfo)) return false; - let context = getCurrentWorkerContext(item, popupNode); + let context = addonInfo.workerContext; if (typeof(context) === "string" && context != "") item.label = context; return !!context; } -// Gets the item's content script worker for a window, creating one if necessary -// Once created it will be automatically destroyed when the window unloads. -// If there is not content scripts for the item then null will be returned. -function getItemWorkerForWindow(item, window) { - if (!item.contentScript && !item.contentScriptFile) - return null; - - let id = getInnerId(window); - let worker = internal(item).workerMap.get(id); - - if (worker) - return worker; - - worker = ContextWorker({ - window: window, - contentScript: item.contentScript, - contentScriptFile: item.contentScriptFile, - onMessage: function(msg) { - emit(item, "message", msg); - }, - onDetach: function() { - internal(item).workerMap.delete(id); - } - }); - - internal(item).workerMap.set(id, worker); - - return worker; -} - // Called when an item is clicked to send out click events to the content // scripts -function itemActivated(item, clickedItem, popupNode) { - let worker = getItemWorkerForWindow(item, popupNode.ownerDocument.defaultView); +function itemActivated(item, clickedNode) { + let data = { + items: [internal(item).id], + data: item.data, + } - if (worker) { - let adjustedNode = popupNode; - for (let context in item.context) - adjustedNode = context.adjustPopupNode(adjustedNode); - worker.fireClick(adjustedNode, clickedItem.data); + while (item.parentMenu) { + item = item.parentMenu; + data.items.push(internal(item).id); } - if (item.parentMenu) - itemActivated(item.parentMenu, clickedItem, popupNode); + let menuData = clickedNode.ownerDocument.defaultView.gContextMenuContentData; + let messageManager = menuData.browser.messageManager; + messageManager.sendAsyncMessage('sdk/contextmenu/activateitems', data, { + popupNode: menuData.popupNode + }); +} + +function serializeItem(item) { + return { + id: internal(item).id, + contexts: [c.serialize() for (c of item.context)], + contentScript: item.contentScript, + contentScriptFile: item.contentScriptFile, + }; } // All things that appear in the context menu extend this let BaseItem = Class({ initialize: function initialize() { - addCollectionProperty(this, "context"); - - // Used to cache content script workers and the windows they have been - // created for - internal(this).workerMap = new Map(); + internal(this).id = uuid(); + internal(this).contexts = []; if ("context" in internal(this).options && internal(this).options.context) { let contexts = internal(this).options.context; if (Array.isArray(contexts)) { for (let context of contexts) - this.context.add(context); + internal(this).contexts.push(context); } else { - this.context.add(contexts); + internal(this).contexts.push(contexts); } } @@ -500,15 +395,59 @@ value: internal(this).options.contentScript }); + // Resolve URIs here as tests may have overriden self + let files = internal(this).options.contentScriptFile; + if (files) { + if (!Array.isArray(files)) + files = [files]; + files = files.map(self.data.url); + } + internal(this).options.contentScriptFile = files; Object.defineProperty(this, "contentScriptFile", { enumerable: true, value: internal(this).options.contentScriptFile }); + + // Notify all frames of this new item + sendItems([serializeItem(this)]); }, destroy: function destroy() { + if (internal(this).destroyed) + return; + + // Tell all existing frames that this item has been destroyed + MessageManager.broadcastAsyncMessage("sdk/contextmenu/destroyitems", { + items: [internal(this).id] + }); + if (this.parentMenu) this.parentMenu.removeItem(this); + + internal(this).destroyed = true; + }, + + get context() { + let contexts = internal(this).contexts.slice(0); + contexts.add = (context) => { + internal(this).contexts.push(context); + // Notify all frames that this item has changed + sendItems([serializeItem(this)]); + }; + contexts.remove = (context) => { + internal(this).contexts = internal(this).contexts.filter(c => { + return c != context; + }); + // Notify all frames that this item has changed + sendItems([serializeItem(this)]); + }; + return contexts; + }, + + set context(val) { + internal(this).contexts = val.slice(0); + // Notify all frames that this item has changed + sendItems([serializeItem(this)]); }, get parentMenu() { @@ -516,6 +455,13 @@ }, }); +function workerMessageReceived({ data: { id, args } }) { + if (internal(this).id != id) + return; + + emit(this, ...args); +} + // All things that have a label on the context menu extend this let LabelledItem = Class({ extends: BaseItem, @@ -524,11 +470,16 @@ initialize: function initialize(options) { BaseItem.prototype.initialize.call(this); EventTarget.prototype.initialize.call(this, options); + + internal(this).messageListener = workerMessageReceived.bind(this); + MessageManager.addMessageListener('sdk/worker/event', internal(this).messageListener); }, destroy: function destroy() { - for (let [,worker] of internal(this).workerMap) - worker.destroy(); + if (internal(this).destroyed) + return; + + MessageManager.removeMessageListener('sdk/worker/event', internal(this).messageListener); BaseItem.prototype.destroy.call(this); }, @@ -712,7 +663,39 @@ let contentContextMenu = ItemContainer(); exports.contentContextMenu = contentContextMenu; +function getContainerItems(container) { + let items = []; + for (let item of internal(container).children) { + items.push(serializeItem(item)); + if (item instanceof Menu) + items = items.concat(getContainerItems(item)); + } + return items; +} + +// Notify all frames of these new or changed items +function sendItems(items) { + MessageManager.broadcastAsyncMessage("sdk/contextmenu/createitems", { + items, + addon: ADDON, + }); +} + +// Called when a new frame is created and wants to get the current list of items +function remoteItemRequest({ target: { messageManager } }) { + let items = getContainerItems(contentContextMenu); + if (items.length == 0) + return; + + messageManager.sendAsyncMessage("sdk/contextmenu/createitems", { + items, + addon: ADDON, + }); +} +MessageManager.addMessageListener('sdk/contextmenu/requestitems', remoteItemRequest); + when(function() { + MessageManager.removeMessageListener('sdk/contextmenu/requestitems', remoteItemRequest); contentContextMenu.destroy(); }); @@ -800,16 +783,16 @@ // Recurses through the menu setting the visibility of items. Returns true // if any of the items in this menu were visible - setVisibility: function setVisibility(menu, popupNode, defaultVisibility) { + setVisibility: function setVisibility(menu, addonInfo, usePageWorker) { let anyVisible = false; for (let item of internal(menu).children) { - let visible = isItemVisible(item, popupNode, defaultVisibility); + let visible = isItemVisible(item, addonInfo[internal(item).id], usePageWorker); // Recurse through Menus, if none of the sub-items were visible then the // menu is hidden too. if (visible && (item instanceof Menu)) - visible = this.setVisibility(item, popupNode, true); + visible = this.setVisibility(item, addonInfo, false); let xulNode = this.getXULNodeForItem(item); xulNode.hidden = !visible; @@ -912,7 +895,7 @@ if (event.target !== xulNode) return; - itemActivated(item, item, self.contextMenu.triggerNode); + itemActivated(item, xulNode); }, false); } @@ -1027,8 +1010,14 @@ this.populate(this.items); } - let popupNode = event.target.triggerNode; - this.setVisibility(this.items, popupNode, PageContext().isCurrent(popupNode)); + let mainWindow = event.target.ownerDocument.defaultView; + this.contextMenuContentData = mainWindow.gContextMenuContentData + let addonInfo = this.contextMenuContentData.addonInfo[self.id]; + if (!addonInfo) { + console.warn("No context menu state data was provided."); + return; + } + this.setVisibility(this.items, addonInfo, true); } catch (e) { console.exception(e); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/test/test-context-menu.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/test/test-context-menu.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/addon-sdk/source/test/test-context-menu.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/addon-sdk/source/test/test-context-menu.js 2014-11-26 21:45:46.000000000 +0000 @@ -11,6 +11,7 @@ const timer = require("sdk/timers"); const { merge } = require("sdk/util/object"); const { defer } = require("sdk/core/promise"); +const observers = require("sdk/system/events"); // These should match the same constants in the module. const ITEM_CLASS = "addon-context-menu-item"; @@ -103,7 +104,7 @@ }); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu([item], [], []); test.done(); }); @@ -125,7 +126,7 @@ }); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { + test.showMenu("#span-link", function (popup) { test.checkMenu([item], [], []); test.done(); }); @@ -209,7 +210,7 @@ ]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, items, []); test.done(); }); @@ -249,9 +250,8 @@ }); test.withTestDoc(function (window, doc) { - let textfield = doc.getElementById("textfield"); - textfield.setSelectionRange(0, textfield.value.length); - test.showMenu(textfield, function (popup) { + test.selectRange("#textfield", 0, null); + test.showMenu("#textfield", function (popup) { test.checkMenu([item], [], []); test.done(); }); @@ -271,9 +271,8 @@ }); test.withTestDoc(function (window, doc) { - let textfield = doc.getElementById("textfield"); - textfield.setSelectionRange(0, 0); - test.showMenu(textfield, function (popup) { + test.selectRange("#textfield", 0, 0); + test.showMenu("#textfield", function (popup) { test.checkMenu([item], [item], []); test.done(); }); @@ -314,25 +313,31 @@ let link = doc.getElementById("targetlink"); link.click(); - test.delayedEventListener(this.tabBrowser, "load", function () { - let browser = test.tabBrowser.selectedBrowser; - let window = browser.contentWindow; - let doc = browser.contentDocument; - window.getSelection().selectAllChildren(doc.body); + let tablistener = event => { + this.tabBrowser.tabContainer.removeEventListener("TabOpen", tablistener, false); + let tab = event.target; + let browser = tab.linkedBrowser; + this.loadFrameScript(browser); + this.delayedEventListener(browser, "load", () => { + let window = browser.contentWindow; + let doc = browser.contentDocument; + window.getSelection().selectAllChildren(doc.body); - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); + test.showMenu(null, function (popup) { + test.checkMenu([item], [], []); + popup.hidePopup(); - test.tabBrowser.removeTab(test.tabBrowser.selectedTab); - test.tabBrowser.selectedTab = test.tab; + test.tabBrowser.removeTab(test.tabBrowser.selectedTab); + test.tabBrowser.selectedTab = test.tab; - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - test.done(); + test.showMenu(null, function (popup) { + test.checkMenu([item], [item], []); + test.done(); + }); }); - }); - }, true); + }, true); + }; + this.tabBrowser.tabContainer.addEventListener("TabOpen", tablistener, false); }); }; @@ -349,8 +354,7 @@ test.withTestDoc(function (window, doc) { window.getSelection().selectAllChildren(doc.body); - let button = doc.getElementById("button"); - test.showMenu(button, function (popup) { + test.showMenu("#button", function (popup) { test.checkMenu([item], [], []); test.done(); }); @@ -369,8 +373,7 @@ }); test.withTestDoc(function (window, doc) { - let button = doc.getElementById("button"); - test.showMenu(button, function (popup) { + test.showMenu("#button", function (popup) { test.checkMenu([item], [item], []); test.done(); }); @@ -436,55 +439,6 @@ }; -// Removing a non-matching URL context after its item is created and the page is -// loaded should cause the item's content script to be evaluated when the -// context menu is next opened. -exports.testURLContextRemove = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let shouldBeEvaled = false; - let context = loader.cm.URLContext("*.bogus.com"); - let item = loader.cm.Item({ - label: "item", - context: context, - contentScript: 'self.postMessage("ok"); self.on("context", function () true);', - onMessage: function (msg) { - assert.ok(shouldBeEvaled, - "content script should be evaluated when expected"); - assert.equal(msg, "ok", "Should have received the right message"); - shouldBeEvaled = false; - } - }); - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - - item.context.remove(context); - - shouldBeEvaled = true; - - test.hideMenu(function () { - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - - assert.ok(!shouldBeEvaled, - "content script should have been evaluated"); - - test.hideMenu(function () { - // Shouldn't get evaluated again - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); - }); - }); - }); - }); -}; - // Loading a new page in the same tab should correctly start a new worker for // any content scripts exports.testPageReload = function (assert, done) { @@ -772,7 +726,7 @@ ]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, [items[2], items[3]], []); test.done(); }); @@ -810,7 +764,7 @@ ]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, items, []); test.done(); }); @@ -848,7 +802,7 @@ ]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, items, []); test.done(); }); @@ -915,7 +869,6 @@ itemScript[1].resolve(); } }); - console.log(item.contentScriptFile, item2.contentScriptFile); test.showMenu(null, function (popup) { test.checkMenu([item, item2], [], []); @@ -949,8 +902,7 @@ }); }; -// Multiple contexts imply intersection, not union, and content context -// listeners should not be called if all declarative contexts are not current. +// Multiple contexts imply intersection, not union. exports.testMultipleContexts = function (assert, done) { let test = new TestHelper(assert, done); let loader = test.newLoader(); @@ -958,14 +910,10 @@ let item = new loader.cm.Item({ label: "item", context: [loader.cm.SelectorContext("a[href]"), loader.cm.PageContext()], - contentScript: 'self.on("context", function () self.postMessage());', - onMessage: function () { - test.fail("Context listener should not be called"); - } }); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { + test.showMenu("#span-link", function (popup) { test.checkMenu([item], [item], []); test.done(); }); @@ -984,7 +932,7 @@ }); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { // The item should be present at first. test.checkMenu([item], [], []); @@ -992,7 +940,35 @@ // Remove the img context and check again. item.context.remove(ctxt); - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { + test.checkMenu([item], [item], []); + test.done(); + }); + }); + }); +}; + +// Once a context is removed, it should no longer cause its item to appear. +exports.testSetContextRemove = function (assert, done) { + let test = new TestHelper(assert, done); + let loader = test.newLoader(); + + let ctxt = loader.cm.SelectorContext("img"); + let item = new loader.cm.Item({ + label: "item", + context: ctxt + }); + + test.withTestDoc(function (window, doc) { + test.showMenu("#image", function (popup) { + + // The item should be present at first. + test.checkMenu([item], [], []); + popup.hidePopup(); + + // Remove the img context and check again. + item.context = []; + test.showMenu("#image", function (popup) { test.checkMenu([item], [item], []); test.done(); }); @@ -1000,6 +976,59 @@ }); }; +// Once a context is added, it should affect whether the item appears. +exports.testAddContext = function (assert, done) { + let test = new TestHelper(assert, done); + let loader = test.newLoader(); + + let ctxt = loader.cm.SelectorContext("img"); + let item = new loader.cm.Item({ + label: "item" + }); + + test.withTestDoc(function (window, doc) { + test.showMenu("#image", function (popup) { + + // The item should not be present at first. + test.checkMenu([item], [item], []); + popup.hidePopup(); + + // Add the img context and check again. + item.context.add(ctxt); + test.showMenu("#image", function (popup) { + test.checkMenu([item], [], []); + test.done(); + }); + }); + }); +}; + +// Once a context is added, it should affect whether the item appears. +exports.testSetContextAdd = function (assert, done) { + let test = new TestHelper(assert, done); + let loader = test.newLoader(); + + let ctxt = loader.cm.SelectorContext("img"); + let item = new loader.cm.Item({ + label: "item" + }); + + test.withTestDoc(function (window, doc) { + test.showMenu("#image", function (popup) { + + // The item should not be present at first. + test.checkMenu([item], [item], []); + popup.hidePopup(); + + // Add the img context and check again. + item.context = [ctxt]; + test.showMenu("#image", function (popup) { + test.checkMenu([item], [], []); + test.done(); + }); + }); + }); +}; // Lots of items should overflow into the overflow submenu. exports.testOverflow = function (assert, done) { @@ -1636,12 +1665,12 @@ let allItems = pItems.concat(aItems); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("link"), function (popup) { + test.showMenu("#link", function (popup) { // The menu should contain all items and will overflow test.checkMenu(allItems, [], []); popup.hidePopup(); - test.showMenu(doc.getElementById("text"), function (popup) { + test.showMenu("#text", function (popup) { // Only contains hald the items and will not overflow test.checkMenu(allItems, aItems, []); popup.hidePopup(); @@ -1651,12 +1680,12 @@ test.checkMenu(allItems, allItems, []); popup.hidePopup(); - test.showMenu(doc.getElementById("text"), function (popup) { + test.showMenu("#text", function (popup) { // Only contains hald the items and will not overflow test.checkMenu(allItems, aItems, []); popup.hidePopup(); - test.showMenu(doc.getElementById("link"), function (popup) { + test.showMenu("#link", function (popup) { // The menu should contain all items and will overflow test.checkMenu(allItems, [], []); popup.hidePopup(); @@ -1666,7 +1695,7 @@ test.checkMenu(allItems, allItems, []); popup.hidePopup(); - test.showMenu(doc.getElementById("link"), function (popup) { + test.showMenu("#link", function (popup) { // The menu should contain all items and will overflow test.checkMenu(allItems, [], []); test.done(); @@ -1758,7 +1787,7 @@ }); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { + test.showMenu("#span-link", function (popup) { test.checkMenu([topMenu], [], []); let topMenuElt = test.getItemElt(popup, topMenu); let topMenuPopup = topMenuElt.firstChild; @@ -1884,7 +1913,7 @@ }); test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { + test.showMenu("#span-link", function (popup) { test.checkMenu([topMenu], [], []); let topMenuElt = test.getItemElt(popup, topMenu); let topMenuPopup = topMenuElt.firstChild; @@ -2224,7 +2253,7 @@ test.done(); } }); - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu([item], [], []); test.getItemElt(popup, item).click(); }); @@ -2560,7 +2589,7 @@ let item = new loader.cm.Item({ label: "item" }); - test.showMenu(doc.getElementById("iframe"), function (popup) { + test.showMenu("#iframe", function (popup) { test.checkMenu([item], [], []); test.done(); }); @@ -3004,7 +3033,7 @@ let hiddenItems = [items[0].items[2]]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, hiddenItems, []); test.done(); }); @@ -3175,7 +3204,7 @@ let frame = doc.getElementById("iframe"); frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body); - test.showMenu(frame.contentDocument.getElementById("text"), function (popup) { + test.showMenu(["#iframe", "#text"], function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3201,7 +3230,7 @@ let frame = doc.getElementById("iframe"); window.getSelection().selectAllChildren(doc.body); - test.showMenu(frame.contentDocument.getElementById("text"), function (popup) { + test.showMenu(["#iframe", "#text"], function (popup) { test.checkMenu(items, items, []); test.done(); }); @@ -3288,7 +3317,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("button"), function (popup) { + test.showMenu("#button", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3310,7 +3339,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("button"), function (popup) { + test.showMenu("#button", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3331,7 +3360,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementsByClassName("predicate-test-a")[0], function (popup) { + test.showMenu(".predicate-test-a", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3352,7 +3381,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("textbox"), function (popup) { + test.showMenu("#textbox", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3373,7 +3402,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("readonly-textbox"), function (popup) { + test.showMenu("#readonly-textbox", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3394,7 +3423,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("disabled-textbox"), function (popup) { + test.showMenu("#disabled-textbox", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3415,7 +3444,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("textfield"), function (popup) { + test.showMenu("#textfield", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3436,7 +3465,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("button"), function (popup) { + test.showMenu("#button", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3458,7 +3487,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3480,7 +3509,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("editable"), function (popup) { + test.showMenu("#editable", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3549,9 +3578,8 @@ test.withTestDoc(function (window, doc) { let textbox = doc.getElementById("textbox"); - textbox.focus(); - textbox.setSelectionRange(3, 6); - test.showMenu(textbox, function (popup) { + test.selectRange("#textbox", 3, 6); + test.showMenu("#textbox", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3574,7 +3602,7 @@ test.withTestDoc(function (window, doc) { image = doc.getElementById("image"); - test.showMenu(image, function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3595,7 +3623,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("link"), function (popup) { + test.showMenu("#link", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3618,7 +3646,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementsByClassName("predicate-test-a")[0], function (popup) { + test.showMenu(".predicate-test-a", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3639,7 +3667,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3660,7 +3688,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("predicate-test-nested-image"), function (popup) { + test.showMenu("#predicate-test-nested-image", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3681,7 +3709,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("predicate-test-nested-structure"), function (popup) { + test.showMenu("#predicate-test-nested-structure", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3703,7 +3731,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("textbox"), function (popup) { + test.showMenu("#textbox", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -3724,7 +3752,7 @@ })]; test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { + test.showMenu("#image", function (popup) { test.checkMenu(items, [], []); test.done(); }); @@ -4098,14 +4126,69 @@ OVERFLOW_THRESH_DEFAULT); }, - // Opens the context menu on the current page. If targetNode is null, the + // Loads scripts necessary in the content process + loadFrameScript: function(browser = this.browserWindow.gBrowser.selectedBrowser) { + function frame_script() { + let { interfaces: Ci } = Components; + addMessageListener('test:contextmenu', ({ data: { selectors } }) => { + let targetNode = null; + let contentWin = content; + if (selectors) { + while (selectors.length) { + targetNode = contentWin.document.querySelector(selectors.shift()); + if (selectors.length) + contentWin = targetNode.contentWindow; + } + } + + let rect = targetNode ? + targetNode.getBoundingClientRect() : + { left: 0, top: 0, width: 0, height: 0 }; + contentWin.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils) + .sendMouseEvent('contextmenu', + rect.left + (rect.width / 2), + rect.top + (rect.height / 2), + 2, 1, 0); + }); + + addMessageListener('test:ping', () => { + sendAsyncMessage('test:pong'); + }); + + addMessageListener('test:select', ({ data: { selector, start, end } }) => { + let element = content.document.querySelector(selector); + element.focus(); + if (end === null) + end = element.value.length; + element.setSelectionRange(start, end); + }); + } + + let messageManager = browser.messageManager; + messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); + }, + + selectRange: function(selector, start, end) { + let messageManager = this.browserWindow.gBrowser.selectedBrowser.messageManager; + messageManager.sendAsyncMessage('test:select', { selector, start, end }); + }, + + // Opens the context menu on the current page. If selectors is null, the // menu is opened in the top-left corner. onShowncallback is passed the - // popup. - showMenu: function(targetNode, onshownCallback) { + // popup. selectors is an array of selectors. Starting from the main document + // each selector points to an iframe, the last selector gives the target node. + // In the simple case of a single selector just that string can be passed + // instead of an array + showMenu: function(selectors, onshownCallback) { let { promise, resolve } = defer(); - function sendEvent() { - this.delayedEventListener(this.browserWindow, "popupshowing", + if (selectors && !Array.isArray(selectors)) + selectors = [selectors]; + + let sendEvent = () => { + let menu = this.browserWindow.document.getElementById("contentAreaContextMenu"); + this.delayedEventListener(menu, "popupshowing", function (e) { let popup = e.target; if (onshownCallback) { @@ -4114,35 +4197,41 @@ resolve(popup); }, false); - let rect = targetNode ? - targetNode.getBoundingClientRect() : - { left: 0, top: 0, width: 0, height: 0 }; - let contentWin = targetNode ? targetNode.ownerDocument.defaultView - : this.browserWindow.content; - contentWin. - QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils). - sendMouseEvent("contextmenu", - rect.left + (rect.width / 2), - rect.top + (rect.height / 2), - 2, 1, 0); + let messageManager = this.browserWindow.gBrowser.selectedBrowser.messageManager; + messageManager.sendAsyncMessage('test:contextmenu', { selectors }); + } + + // Bounces an asynchronous message through the browser message manager. + // This ensures that any pending messages have been delivered to the frame + // scripts and so the remote proxies have been updated + let flushMessages = () => { + let listener = () => { + messageManager.removeMessageListener('test:pong', listener); + sendEvent(); + }; + + let messageManager = this.browserWindow.gBrowser.selectedBrowser.messageManager; + messageManager.addMessageListener('test:pong', listener); + messageManager.sendAsyncMessage('test:ping'); } // If a new tab or window has not yet been opened, open a new tab now. For // some reason using the tab already opened when the test starts causes // leaks. See bug 566351 for details. - if (!targetNode && !this.oldSelectedTab && !this.oldBrowserWindow) { + if (!selectors && !this.oldSelectedTab && !this.oldBrowserWindow) { this.oldSelectedTab = this.tabBrowser.selectedTab; this.tab = this.tabBrowser.addTab("about:blank"); let browser = this.tabBrowser.getBrowserForTab(this.tab); this.delayedEventListener(browser, "load", function () { this.tabBrowser.selectedTab = this.tab; - sendEvent.call(this); + this.loadFrameScript(); + flushMessages(); }, true); } - else - sendEvent.call(this); + else { + flushMessages(); + } return promise; }, @@ -4155,9 +4244,14 @@ // Opens a new browser window. The window will be closed automatically when // done() is called. - withNewWindow: function (onloadCallback) { - let win = this.browserWindow.OpenBrowserWindow(); - this.delayedEventListener(win, "load", onloadCallback, true); + withNewWindow: function (onloadCallback, makePrivate = false) { + let win = this.browserWindow.OpenBrowserWindow({ private: makePrivate }); + observers.once("browser-delayed-startup-finished", () => { + // Open a new tab so we can make sure it is remote and loaded + win.gBrowser.selectedTab = win.gBrowser.addTab(); + this.loadFrameScript(); + this.delayedEventListener(win.gBrowser.selectedBrowser, "load", onloadCallback, true); + }); this.oldBrowserWindow = this.browserWindow; this.browserWindow = win; }, @@ -4165,10 +4259,7 @@ // Opens a new private browser window. The window will be closed // automatically when done() is called. withNewPrivateWindow: function (onloadCallback) { - let win = this.browserWindow.OpenBrowserWindow({private: true}); - this.delayedEventListener(win, "load", onloadCallback, true); - this.oldBrowserWindow = this.browserWindow; - this.browserWindow = win; + this.withNewWindow(onloadCallback, true); }, // Opens a new tab with our test page in the current window. The tab will @@ -4180,6 +4271,7 @@ this.delayedEventListener(browser, "load", function () { this.tabBrowser.selectedTab = this.tab; + this.loadFrameScript(); onloadCallback.call(this, browser.contentWindow, browser.contentDocument); }, true, function(evt) { return evt.target.location == TEST_DOC_URL; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/app/b2g.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/app/b2g.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/app/b2g.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/app/b2g.js 2014-11-26 21:45:46.000000000 +0000 @@ -433,7 +433,8 @@ pref("dom.ipc.processCount", 100000); pref("dom.ipc.browser_frames.oop_by_default", false); -pref("dom.browser_frames.useAsyncPanZoom", true); + +pref("dom.meta-viewport.enabled", true); // SMS/MMS pref("dom.sms.enabled", true); @@ -1008,9 +1009,9 @@ // Overscroll-related settings pref("apz.overscroll.enabled", true); -pref("apz.overscroll.stretch_factor", "0.5"); -pref("apz.overscroll.spring_stiffness", "0.001"); -pref("apz.overscroll.spring_friction", "0.015"); +pref("apz.overscroll.stretch_factor", "0.15"); +pref("apz.overscroll.spring_stiffness", "0.002"); +pref("apz.overscroll.spring_friction", "0.02"); pref("apz.overscroll.stop_distance_threshold", "5.0"); pref("apz.overscroll.stop_velocity_threshold", "0.01"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/app/Makefile.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/app/Makefile.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/app/Makefile.in 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/app/Makefile.in 2014-11-26 21:45:46.000000000 +0000 @@ -20,14 +20,6 @@ # Make sure the standalone glue doesn't try to get libxpcom.so from b2g/app. NSDISTMODE = copy -# Copy the Firefox OS fonts if available -ifdef MOZTTDIR -include $(MOZTTDIR)/fonts.mk -MOZTT_DEST = $(FINAL_TARGET)/fonts -MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/%,$(subst :, ,$(PRODUCT_COPY_FILES)))) -INSTALL_TARGETS += MOZTT -endif - include $(topsrcdir)/config/rules.mk APP_ICON = b2g diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/branding/unofficial/configure.sh thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/branding/unofficial/configure.sh --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/branding/unofficial/configure.sh 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/branding/unofficial/configure.sh 2014-11-26 21:45:46.000000000 +0000 @@ -2,6 +2,6 @@ # 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/. -ANDROID_PACKAGE_NAME=org.mozilla.b2g_`echo $USER` +ANDROID_PACKAGE_NAME=org.mozilla.b2g_`echo $USER | sed 's/-/_/g'` MOZ_APP_DISPLAYNAME=B2G MOZ_UPDATER= diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/chrome/content/desktop.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/chrome/content/desktop.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/chrome/content/desktop.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/chrome/content/desktop.js 2014-11-26 21:45:46.000000000 +0000 @@ -30,11 +30,15 @@ // so that click events are delayed and it is better to // listen for touch events. homeButton.addEventListener('touchstart', function() { - shell.sendChromeEvent({type: 'home-button-press'}); + let window = shell.contentBrowser.contentWindow; + let e = new window.KeyboardEvent('keydown', {key: 'Home'}); + window.dispatchEvent(e); homeButton.classList.add('active'); }); homeButton.addEventListener('touchend', function() { - shell.sendChromeEvent({type: 'home-button-release'}); + let window = shell.contentBrowser.contentWindow; + let e = new window.KeyboardEvent('keyup', {key: 'Home'}); + window.dispatchEvent(e); homeButton.classList.remove('active'); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/chrome/content/settings.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/chrome/content/settings.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/chrome/content/settings.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/chrome/content/settings.js 2014-11-26 21:45:46.000000000 +0000 @@ -510,10 +510,6 @@ defaultValue: 0 }, 'app.update.interval': 86400, - 'apz.force-enable': { - prefName: 'dom.browser_frames.useAsyncPanZoom', - defaultValue: false - }, 'apz.overscroll.enabled': true, 'debug.fps.enabled': { prefName: 'layers.acceleration.draw-fps', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/LogCapture.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/LogCapture.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/LogCapture.jsm 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/LogCapture.jsm 2014-11-26 21:45:46.000000000 +0000 @@ -8,22 +8,27 @@ this.EXPORTED_SYMBOLS = ['LogCapture']; -/** - * readLogFile - * Read in /dev/log/{{log}} in nonblocking mode, which will return -1 if - * reading would block the thread. - * - * @param log {String} The log from which to read. Must be present in /dev/log - * @return {Uint8Array} Raw log data - */ -let readLogFile = function(logLocation) { - if (!this.ctypes) { +const SYSTEM_PROPERTY_KEY_MAX = 32; +const SYSTEM_PROPERTY_VALUE_MAX = 92; + +function debug(msg) { + dump('LogCapture.jsm: ' + msg + '\n'); +} + +let LogCapture = { + ensureLoaded: function() { + if (!this.ctypes) { + this.load(); + } + }, + + load: function() { // load in everything on first use Components.utils.import('resource://gre/modules/ctypes.jsm', this); - this.lib = this.ctypes.open(this.ctypes.libraryName('c')); + this.libc = this.ctypes.open(this.ctypes.libraryName('c')); - this.read = this.lib.declare('read', + this.read = this.libc.declare('read', this.ctypes.default_abi, this.ctypes.int, // bytes read (out) this.ctypes.int, // file descriptor (in) @@ -31,61 +36,124 @@ this.ctypes.size_t // size_t size of buffer (in) ); - this.open = this.lib.declare('open', + this.open = this.libc.declare('open', this.ctypes.default_abi, this.ctypes.int, // file descriptor (returned) this.ctypes.char.ptr, // path this.ctypes.int // flags ); - this.close = this.lib.declare('close', + this.close = this.libc.declare('close', this.ctypes.default_abi, this.ctypes.int, // error code (returned) this.ctypes.int // file descriptor ); - } - const O_READONLY = 0; - const O_NONBLOCK = 1 << 11; + this.property_find_nth = + this.libc.declare("__system_property_find_nth", + this.ctypes.default_abi, + this.ctypes.voidptr_t, // return value: nullable prop_info* + this.ctypes.unsigned_int); // n: the index of the property to return + + this.property_read = + this.libc.declare("__system_property_read", + this.ctypes.default_abi, + this.ctypes.void_t, // return: none + this.ctypes.voidptr_t, // non-null prop_info* + this.ctypes.char.ptr, // key + this.ctypes.char.ptr); // value + + this.key_buf = this.ctypes.char.array(SYSTEM_PROPERTY_KEY_MAX)(); + this.value_buf = this.ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)(); + }, + + cleanup: function() { + this.libc.close(); + + this.read = null; + this.open = null; + this.close = null; + this.property_find_nth = null; + this.property_read = null; + this.key_buf = null; + this.value_buf = null; + + this.libc = null; + this.ctypes = null; + }, + + /** + * readLogFile + * Read in /dev/log/{{log}} in nonblocking mode, which will return -1 if + * reading would block the thread. + * + * @param log {String} The log from which to read. Must be present in /dev/log + * @return {Uint8Array} Raw log data + */ + readLogFile: function(logLocation) { + this.ensureLoaded(); + + const O_READONLY = 0; + const O_NONBLOCK = 1 << 11; + + const BUF_SIZE = 2048; + + let BufType = this.ctypes.ArrayType(this.ctypes.char); + let buf = new BufType(BUF_SIZE); + let logArray = []; + + let logFd = this.open(logLocation, O_READONLY | O_NONBLOCK); + if (logFd === -1) { + return null; + } - const BUF_SIZE = 2048; + let readStart = Date.now(); + let readCount = 0; + while (true) { + let count = this.read(logFd, buf, BUF_SIZE); + readCount += 1; + + if (count <= 0) { + // log has return due to being nonblocking or running out of things + break; + } + for(let i = 0; i < count; i++) { + logArray.push(buf[i]); + } + } - let BufType = this.ctypes.ArrayType(this.ctypes.char); - let buf = new BufType(BUF_SIZE); - let logArray = []; - - let logFd = this.open(logLocation, O_READONLY | O_NONBLOCK); - if (logFd === -1) { - return null; - } + let logTypedArray = new Uint8Array(logArray); - let readStart = Date.now(); - let readCount = 0; - while (true) { - let count = this.read(logFd, buf, BUF_SIZE); - readCount += 1; - - if (count <= 0) { - // log has return due to being nonblocking or running out of things - break; - } - for(let i = 0; i < count; i++) { - logArray.push(buf[i]); - } - } + this.close(logFd); - let logTypedArray = new Uint8Array(logArray); + return logTypedArray; + }, - this.close(logFd); + /** + * Get all system properties as a dict with keys mapping to values + */ + readProperties: function() { + this.ensureLoaded(); + let n = 0; + let propertyDict = {}; + + while(true) { + let prop_info = this.property_find_nth(n); + if(prop_info.isNull()) { + break; + } + + // read the prop_info into the key and value buffers + this.property_read(prop_info, this.key_buf, this.value_buf); + let key = this.key_buf.readString();; + let value = this.value_buf.readString() - return logTypedArray; -}; + propertyDict[key] = value; + n++; + } -let cleanup = function() { - this.lib.close(); - this.read = this.open = this.close = null; - this.lib = null; - this.ctypes = null; + return propertyDict; + } }; -this.LogCapture = { readLogFile: readLogFile, cleanup: cleanup }; +this.LogCapture = LogCapture; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/LogParser.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/LogParser.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/LogParser.jsm 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/LogParser.jsm 2014-11-26 21:45:46.000000000 +0000 @@ -215,71 +215,14 @@ } /** - * Parse an array of bytes as a properties file. The structure of the - * properties file is derived from bionic/libc/bionic/system_properties.c - * @param array {Uint8Array} Array containing property data - * @return {Object} Map from property name to property value, both strings - */ -function parsePropertiesArray(array) { - let data = new DataView(array.buffer); - let byteString = String.fromCharCode.apply(null, array); - - let properties = {}; - - let propIndex = 0; - let propCount = data.getUint32(0, true); - - // first TOC entry is at 32 - let tocOffset = 32; - - const PROP_NAME_MAX = 32; - const PROP_VALUE_MAX = 92; - - while (propIndex < propCount) { - // Retrieve offset from file start - let infoOffset = data.getUint32(tocOffset, true) & 0xffffff; - - // Now read the name, integer serial, and value - let propName = ""; - let nameOffset = infoOffset; - while (byteString[nameOffset] != "\0" && - (nameOffset - infoOffset) < PROP_NAME_MAX) { - propName += byteString[nameOffset]; - nameOffset ++; - } - - infoOffset += PROP_NAME_MAX; - // Skip serial number - infoOffset += 4; - - let propValue = ""; - nameOffset = infoOffset; - while (byteString[nameOffset] != "\0" && - (nameOffset - infoOffset) < PROP_VALUE_MAX) { - propValue += byteString[nameOffset]; - nameOffset ++; - } - - // Move to next table of contents entry - tocOffset += 4; - - properties[propName] = propValue; - propIndex += 1; - } - - return properties; -} - -/** - * Pretty-print an array read from the /dev/__properties__ file. - * @param array {Uint8Array} File data array + * Pretty-print an array read from the list of propreties. + * @param {Object} Object representing the properties * @return {String} Human-readable string of property name: property value */ -function prettyPrintPropertiesArray(array) { - let properties = parsePropertiesArray(array); +function prettyPrintPropertiesArray(properties) { let propertiesString = ""; for(let propName in properties) { - propertiesString += propName + ": " + properties[propName] + "\n"; + propertiesString += "[" + propName + "]: [" + properties[propName] + "]\n"; } return propertiesString; } @@ -294,7 +237,6 @@ this.LogParser = { parseLogArray: parseLogArray, - parsePropertiesArray: parsePropertiesArray, prettyPrintArray: prettyPrintArray, prettyPrintLogArray: prettyPrintLogArray, prettyPrintPropertiesArray: prettyPrintPropertiesArray diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/LogShake.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/LogShake.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/LogShake.jsm 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/LogShake.jsm 2014-11-26 21:45:46.000000000 +0000 @@ -79,7 +79,6 @@ * Map of files which have log-type information to their parsers */ LOGS_WITH_PARSERS: { - '/dev/__properties__': LogParser.prettyPrintPropertiesArray, '/dev/log/main': LogParser.prettyPrintLogArray, '/dev/log/system': LogParser.prettyPrintLogArray, '/dev/log/radio': LogParser.prettyPrintLogArray, @@ -210,6 +209,14 @@ */ readLogs: function() { let logArrays = {}; + + try { + logArrays["properties"] = + LogParser.prettyPrintPropertiesArray(LogCapture.readProperties()); + } catch (ex) { + Cu.reportError("Unable to get device properties: " + ex); + } + for (let loc in this.LOGS_WITH_PARSERS) { let logArray; try { Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/data/test_properties and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/data/test_properties differ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/test_logcapture.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/test_logcapture.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/test_logcapture.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/test_logcapture.js 2014-11-26 21:45:46.000000000 +0000 @@ -8,7 +8,7 @@ * log devices */ function run_test() { - Components.utils.import('resource:///modules/LogCapture.jsm'); + Components.utils.import("resource:///modules/LogCapture.jsm"); function verifyLog(log) { // log exists @@ -17,9 +17,14 @@ ok(log.length >= 0); } - let mainLog = LogCapture.readLogFile('/dev/log/main'); + let propertiesLog = LogCapture.readProperties(); + notEqual(propertiesLog, null, "Properties should not be null"); + notEqual(propertiesLog, undefined, "Properties should not be undefined"); + equal(propertiesLog["ro.kernel.qemu"], "1", "QEMU property should be 1"); + + let mainLog = LogCapture.readLogFile("/dev/log/main"); verifyLog(mainLog); - let meminfoLog = LogCapture.readLogFile('/proc/meminfo'); + let meminfoLog = LogCapture.readLogFile("/proc/meminfo"); verifyLog(meminfoLog); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/test_logparser.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/test_logparser.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/test_logparser.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/test_logparser.js 2014-11-26 21:45:46.000000000 +0000 @@ -2,48 +2,73 @@ const {utils: Cu, classes: Cc, interfaces: Ci} = Components; +function debug(msg) { + var timestamp = Date.now(); + dump("LogParser: " + timestamp + ": " + msg + "\n"); +} + function run_test() { - Cu.import('resource:///modules/LogParser.jsm'); + Cu.import("resource:///modules/LogParser.jsm"); + debug("Starting"); + run_next_test(); +} - let propertiesFile = do_get_file('data/test_properties'); - let loggerFile = do_get_file('data/test_logger_file'); +function makeStream(file) { + var fileStream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + fileStream.init(file, -1, -1, 0); + var bis = Cc["@mozilla.org/binaryinputstream;1"] + .createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(fileStream); + return bis; +} + +add_test(function test_parse_logfile() { + let loggerFile = do_get_file("data/test_logger_file"); - let propertiesStream = makeStream(propertiesFile); let loggerStream = makeStream(loggerFile); // Initialize arrays to hold the file contents (lengths are hardcoded) - let propertiesArray = new Uint8Array(propertiesStream.readByteArray(65536)); let loggerArray = new Uint8Array(loggerStream.readByteArray(4037)); - propertiesStream.close(); loggerStream.close(); - let properties = LogParser.parsePropertiesArray(propertiesArray); let logMessages = LogParser.parseLogArray(loggerArray); - // Test arbitrary property entries for correctness - equal(properties['ro.boot.console'], 'ttyHSL0'); - equal(properties['net.tcp.buffersize.lte'], - '524288,1048576,2097152,262144,524288,1048576'); - - ok(logMessages.length === 58, 'There should be 58 messages in the log'); + ok(logMessages.length === 58, "There should be 58 messages in the log"); let expectedLogEntry = { processId: 271, threadId: 271, seconds: 790796, nanoseconds: 620000001, time: 790796620.000001, - priority: 4, tag: 'Vold', - message: 'Vold 2.1 (the revenge) firing up\n' + priority: 4, tag: "Vold", + message: "Vold 2.1 (the revenge) firing up\n" }; deepEqual(expectedLogEntry, logMessages[0]); -} + run_next_test(); +}); -function makeStream(file) { - var fileStream = Cc['@mozilla.org/network/file-input-stream;1'] - .createInstance(Ci.nsIFileInputStream); - fileStream.init(file, -1, -1, 0); - var bis = Cc['@mozilla.org/binaryinputstream;1'] - .createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(fileStream); - return bis; -} +add_test(function test_print_properties() { + let properties = { + "ro.secure": "1", + "sys.usb.state": "diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb" + }; + + let logMessages = LogParser.prettyPrintPropertiesArray(properties); + let logMessagesArray = logMessages.split("\n"); + + ok(logMessagesArray.length === 3, "There should be 3 lines in the log."); + notEqual(logMessagesArray[0], "", "First line should not be empty"); + notEqual(logMessagesArray[1], "", "Second line should not be empty"); + equal(logMessagesArray[2], "", "Last line should be empty"); + + let expectedLog = [ + "[ro.secure]: [1]", + "[sys.usb.state]: [diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb]", + "" + ].join("\n"); + + deepEqual(expectedLog, logMessages); + + run_next_test(); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/test_logshake.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/test_logshake.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/test_logshake.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/test_logshake.js 2014-11-26 21:45:46.000000000 +0000 @@ -8,19 +8,19 @@ /* disable use strict warning */ /* jshint -W097 */ -'use strict'; +"use strict"; const Cu = Components.utils; -Cu.import('resource://gre/modules/LogCapture.jsm'); -Cu.import('resource://gre/modules/LogShake.jsm'); +Cu.import("resource://gre/modules/LogCapture.jsm"); +Cu.import("resource://gre/modules/LogShake.jsm"); // Force logshake to handle a device motion event with given components // Does not use SystemAppProxy because event needs special // accelerationIncludingGravity property function sendDeviceMotionEvent(x, y, z) { let event = { - type: 'devicemotion', + type: "devicemotion", accelerationIncludingGravity: { x: x, y: y, @@ -34,7 +34,7 @@ // conditions. function sendScreenChangeEvent(screenEnabled) { let event = { - type: 'screenchange', + type: "screenchange", detail: { screenEnabled: screenEnabled } @@ -44,7 +44,7 @@ function debug(msg) { var timestamp = Date.now(); - dump('LogShake: ' + timestamp + ': ' + msg); + dump("LogShake: " + timestamp + ": " + msg); } add_test(function test_do_log_capture_after_shaking() { @@ -61,7 +61,7 @@ sendDeviceMotionEvent(9001, 9001, 9001); ok(readLocations.length > 0, - 'LogShake should attempt to read at least one log'); + "LogShake should attempt to read at least one log"); LogShake.uninit(); run_next_test(); @@ -81,15 +81,15 @@ sendDeviceMotionEvent(0, 9.8, 9.8); ok(readLocations.length === 0, - 'LogShake should not read any logs'); + "LogShake should not read any logs"); - debug('test_do_nothing_when_resting: stop'); + debug("test_do_nothing_when_resting: stop"); LogShake.uninit(); run_next_test(); }); add_test(function test_do_nothing_when_disabled() { - debug('test_do_nothing_when_disabled: start'); + debug("test_do_nothing_when_disabled: start"); // Disable LogShake LogShake.uninit(); @@ -103,7 +103,7 @@ sendDeviceMotionEvent(0, 9001, 9001); ok(readLocations.length === 0, - 'LogShake should not read any logs'); + "LogShake should not read any logs"); run_next_test(); }); @@ -126,7 +126,7 @@ sendDeviceMotionEvent(0, 9001, 9001); ok(readLocations.length === 0, - 'LogShake should not read any logs'); + "LogShake should not read any logs"); // Restore the screen sendScreenChangeEvent(true); @@ -149,7 +149,7 @@ sendDeviceMotionEvent(9001, 9001, 9001); ok(readLocations.length > 0, - 'LogShake should attempt to read at least one log'); + "LogShake should attempt to read at least one log"); LogShake.uninit(); run_next_test(); @@ -172,13 +172,13 @@ sendDeviceMotionEvent(9001, 9001, 9001); ok(readLocations.length > 0, - 'LogShake should attempt to read at least one log'); + "LogShake should attempt to read at least one log"); LogShake.uninit(); run_next_test(); }); function run_test() { - debug('Starting'); + debug("Starting"); run_next_test(); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/xpcshell.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/xpcshell.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/components/test/unit/xpcshell.ini 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/components/test/unit/xpcshell.ini 2014-11-26 21:45:46.000000000 +0000 @@ -4,7 +4,6 @@ support-files = data/test_logger_file - data/test_properties [test_bug793310.js] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/dolphin/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/dolphin/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/dolphin/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/dolphin/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -15,15 +15,15 @@ - + - + - + - + @@ -111,7 +111,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -19,13 +19,13 @@ - - + + - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator-ics/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator-ics/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator-ics/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator-ics/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -19,13 +19,13 @@ - - + + - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator-jb/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator-jb/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator-jb/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator-jb/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -17,10 +17,10 @@ - - - - + + + + @@ -134,7 +134,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator-kk/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator-kk/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/emulator-kk/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/emulator-kk/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -15,15 +15,15 @@ - + - + - + - + @@ -111,7 +111,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/flame/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/flame/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/flame/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/flame/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -17,10 +17,10 @@ - - - - + + + + @@ -122,7 +122,7 @@ - + @@ -145,7 +145,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/flame-kk/releng-flame-kk.tt thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/flame-kk/releng-flame-kk.tt --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/flame-kk/releng-flame-kk.tt 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/flame-kk/releng-flame-kk.tt 2014-11-26 21:45:46.000000000 +0000 @@ -1,8 +1,9 @@ [ { -"size": 91247216, -"digest": "2b4be549f98695488ea7288d9e7f8ac0fa45112bedefa485a6e016c4af73fa21bb6b3992beda516f268417207c5deb57afad3959d3b1fbd07d5269b3a6be6a27", +"size": 120750384, +"digest": "0e0a0b0dcca020e3283ce8deb33d0eed48fab16ef2fd919120bd7b5abba00713210be17f466d11bf77cca3c9e3b663805be61774476cc669f0a75736d901edfd", "algorithm": "sha512", -"filename": "backup-flame.tar.xz" +"filename": "backup-flame.tar.xz", +"comment": "v188-1" } ] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/flame-kk/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/flame-kk/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/flame-kk/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/flame-kk/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -15,15 +15,15 @@ - + - + - + - + @@ -111,7 +111,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -153,7 +153,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/gaia.json thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/gaia.json --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/gaia.json 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/gaia.json 2014-11-26 21:45:46.000000000 +0000 @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "26b4d06af9d942c3b6ab81f119d33951823bc256", + "revision": "769491b138582de92f5636413928de13268e1a63", "repo_path": "integration/gaia-central" } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/hamachi/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/hamachi/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/hamachi/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/hamachi/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -17,11 +17,11 @@ - - + + - - + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/helix/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/helix/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/helix/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/helix/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -15,11 +15,11 @@ - - + + - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/debug thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/debug --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/debug 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/debug 2014-11-26 21:45:46.000000000 +0000 @@ -10,7 +10,6 @@ export TOOLCHAIN_HOST=linux-x86 export GONK_PRODUCT=generic ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-" -ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols ac_add_options --enable-debug #. "$topsrcdir/build/mozconfig.cache" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/nightly thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/nightly --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/nightly 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/ics_armv7a_gecko/nightly 2014-11-26 21:45:46.000000000 +0000 @@ -11,7 +11,6 @@ export TOOLCHAIN_HOST=linux-x86 export GONK_PRODUCT=generic ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-" -ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols # ac_add_options --enable-profiling #. "$topsrcdir/build/mozconfig.cache" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux32_gecko/debug thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux32_gecko/debug --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux32_gecko/debug 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux32_gecko/debug 2014-11-26 21:45:46.000000000 +0000 @@ -29,7 +29,6 @@ #B2G options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux32_gecko/nightly thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux32_gecko/nightly --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux32_gecko/nightly 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux32_gecko/nightly 2014-11-26 21:45:46.000000000 +0000 @@ -27,7 +27,6 @@ #B2G options ac_add_options --enable-application=b2g -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux64_gecko/debug thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux64_gecko/debug --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux64_gecko/debug 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux64_gecko/debug 2014-11-26 21:45:46.000000000 +0000 @@ -29,7 +29,6 @@ #B2G options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux64_gecko/nightly thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux64_gecko/nightly --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/mozconfigs/linux64_gecko/nightly 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/mozconfigs/linux64_gecko/nightly 2014-11-26 21:45:46.000000000 +0000 @@ -27,7 +27,6 @@ #B2G options ac_add_options --enable-application=b2g -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/nexus-4/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/nexus-4/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/nexus-4/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/nexus-4/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -17,10 +17,10 @@ - - - - + + + + @@ -129,7 +129,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/wasabi/sources.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/wasabi/sources.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/config/wasabi/sources.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/config/wasabi/sources.xml 2014-11-26 21:45:46.000000000 +0000 @@ -17,12 +17,12 @@ - - + + - - + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/installer/Makefile.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/installer/Makefile.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/installer/Makefile.in 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/installer/Makefile.in 2014-11-26 21:45:46.000000000 +0000 @@ -83,9 +83,6 @@ DEFINES += -DGKMEDIAS_SHARED_LIBRARY endif -ifdef MOZ_REPLACE_MALLOC -DEFINES += -DMOZ_REPLACE_MALLOC -endif ifdef MOZ_JEMALLOC3 DEFINES += -DMOZ_JEMALLOC3 endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/installer/package-manifest.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/installer/package-manifest.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/installer/package-manifest.in 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/installer/package-manifest.in 2014-11-26 21:45:46.000000000 +0000 @@ -449,6 +449,10 @@ @BINPATH@/components/RadioInterfaceLayer.js @BINPATH@/components/RadioInterfaceLayer.manifest @BINPATH@/components/RILContentHelper.js +@BINPATH@/components/RILSystemMessengerHelper.js +@BINPATH@/components/RILSystemMessengerHelper.manifest +@BINPATH@/components/TelephonyAudioService.js +@BINPATH@/components/TelephonyAudioService.manifest @BINPATH@/components/TelephonyService.js @BINPATH@/components/TelephonyService.manifest @BINPATH@/components/VoicemailService.js diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/locales/en-US/chrome/overrides/appstrings.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/locales/en-US/chrome/overrides/appstrings.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/b2g/locales/en-US/chrome/overrides/appstrings.properties 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/b2g/locales/en-US/chrome/overrides/appstrings.properties 2014-11-26 21:45:46.000000000 +0000 @@ -31,6 +31,6 @@ externalProtocolLaunchBtn=Launch application malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences. phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information. -cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way. +cspBlocked=This page has a content security policy that prevents it from being loaded in this way. corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected. remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/blocklist.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/blocklist.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/blocklist.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/blocklist.xml 2014-11-26 21:45:46.000000000 +0000 @@ -1,5 +1,5 @@ - + @@ -451,10 +451,8 @@ - - - - + + @@ -534,14 +532,22 @@ + + + + + + - - + + + + @@ -887,6 +893,12 @@ + + + + + + @@ -1458,6 +1470,12 @@ + + + + + + @@ -1543,6 +1561,12 @@ + + + + + + @@ -2019,6 +2043,12 @@ + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/moz.build 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/moz.build 2014-11-26 21:45:46.000000000 +0000 @@ -6,7 +6,7 @@ DIRS += ['profile/extensions'] -if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_METRO']: +if CONFIG['OS_ARCH'] == 'WINNT' and (CONFIG['MOZ_METRO'] or CONFIG['MOZ_ASAN']): GeckoProgram(CONFIG['MOZ_APP_NAME']) else: GeckoProgram(CONFIG['MOZ_APP_NAME'], msvcrt='static') diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/nsBrowserApp.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/nsBrowserApp.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/nsBrowserApp.cpp 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/nsBrowserApp.cpp 2014-11-26 21:45:46.000000000 +0000 @@ -37,6 +37,11 @@ #ifdef XP_WIN // we want a wmain entry point +#ifdef MOZ_ASAN +// ASAN requires firefox.exe to be built with -MD, and it's OK if we don't +// support Windows XP SP2 in ASAN builds. +#define XRE_DONT_SUPPORT_XPSP2 +#endif #include "nsWindowsWMain.cpp" #define snprintf _snprintf #define strcasecmp _stricmp @@ -121,7 +126,7 @@ return false; } -#ifdef XP_WIN +#if defined(XP_WIN) && defined(MOZ_METRO) /* * AttachToTestHarness - Windows helper for when we are running * in the immersive environment. Firefox is launched by Windows in diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/profile/firefox.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/profile/firefox.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/app/profile/firefox.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/app/profile/firefox.js 2014-11-26 21:45:46.000000000 +0000 @@ -183,7 +183,7 @@ pref("app.update.silent", false); // If set to true, the hamburger button will show badges for update events. -#ifdef MOZ_DEV_EDITION +#ifndef RELEASE_BUILD pref("app.update.badge", true); #else pref("app.update.badge", false); @@ -323,7 +323,7 @@ pref("browser.urlbar.autoFill.typed", true); // Use the new unifiedComplete component -pref("browser.urlbar.unifiedcomplete", true); +pref("browser.urlbar.unifiedcomplete", false); // 0: Match anywhere (e.g., middle of words) // 1: Match on word boundaries and then try matching anywhere @@ -1319,7 +1319,7 @@ pref("devtools.devedition.promo.url", "https://mozilla.org/firefox/developer"); // Only potentially show in beta release -#ifdef MOZ_UPDATE_CHANNEL == beta +#if MOZ_UPDATE_CHANNEL == beta pref("devtools.devedition.promo.enabled", true); #else pref("devtools.devedition.promo.enabled", false); @@ -1642,8 +1642,10 @@ pref("image.mem.max_decoded_image_kb", 256000); pref("loop.enabled", true); -pref("loop.server", "https://loop.services.mozilla.com"); +pref("loop.server", "https://loop.services.mozilla.com/v0"); pref("loop.seenToS", "unseen"); +pref("loop.gettingStarted.seen", false); +pref("loop.gettingStarted.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/hello/start"); pref("loop.learnMoreUrl", "https://www.firefox.com/hello/"); pref("loop.legal.ToS_url", "https://hello.firefox.com/legal/terms/"); pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/"); @@ -1664,9 +1666,10 @@ #endif pref("loop.oauth.google.redirect_uri", "urn:ietf:wg:oauth:2.0:oob:auto"); pref("loop.oauth.google.scope", "https://www.google.com/m8/feeds"); -pref("loop.rooms.enabled", false); +pref("loop.rooms.enabled", true); pref("loop.fxa_oauth.tokendata", ""); pref("loop.fxa_oauth.profile", ""); +pref("loop.support_url", "https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc"); // serverURL to be assigned by services team pref("services.push.serverURL", "wss://push.services.mozilla.com/"); @@ -1808,7 +1811,7 @@ #endif #ifdef NIGHTLY_BUILD -pref("browser.tabs.remote.autostart.1", true); +pref("browser.tabs.remote.autostart.1", false); #endif // Temporary pref to allow printing in e10s windows on some platforms. @@ -1818,4 +1821,9 @@ pref("print.enable_e10s_testing", true); #endif +#ifdef NIGHTLY_BUILD +// Enable e10s add-on interposition by default. +pref("extensions.interposition.enabled", true); +#endif + pref("browser.defaultbrowser.notificationbar", false); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/aboutaccounts/aboutaccounts.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/aboutaccounts/aboutaccounts.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/aboutaccounts/aboutaccounts.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/aboutaccounts/aboutaccounts.js 2014-11-26 21:45:46.000000000 +0000 @@ -99,16 +99,6 @@ iframe: null, init: function (url, urlParams) { - let weave = Cc["@mozilla.org/weave/service;1"] - .getService(Ci.nsISupports) - .wrappedJSObject; - - // Don't show about:accounts with FxA disabled. - if (!weave.fxAccountsEnabled) { - document.body.remove(); - return; - } - // If a master-password is enabled, we want to encourage the user to // unlock it. Things still work if not, but the user will probably need // to re-auth next startup (in which case we will get here again and diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/aboutNetError.xhtml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/aboutNetError.xhtml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/aboutNetError.xhtml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/aboutNetError.xhtml 2014-11-26 21:45:46.000000000 +0000 @@ -186,8 +186,8 @@ document.getElementById("errorTryAgain").style.display = "none"; } - if (err == "cspFrameAncestorBlocked") { - // Remove the "Try again" button for CSP frame ancestors violation, since it's + if (err == "cspBlocked") { + // Remove the "Try again" button for CSP violations, since it's // almost certainly useless. (Bug 553180) document.getElementById("errorTryAgain").style.display = "none"; } @@ -353,7 +353,7 @@

&nssFailure2.title;

&nssBadCert.title;

&malwareBlocked.title;

-

&cspFrameAncestorBlocked.title;

+

&cspBlocked.title;

&remoteXUL.title;

&corruptedContentError.title;

@@ -379,7 +379,7 @@
&nssFailure2.longDesc2;
&nssBadCert.longDesc2;
&malwareBlocked.longDesc;
-
&cspFrameAncestorBlocked.longDesc;
+
&cspBlocked.longDesc;
&remoteXUL.longDesc;
&corruptedContentError.longDesc;
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/aboutTabCrashed.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/aboutTabCrashed.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/aboutTabCrashed.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/aboutTabCrashed.js 2014-11-26 21:45:46.000000000 +0000 @@ -12,6 +12,22 @@ document.title = parseQueryString(); +addEventListener("DOMContentLoaded", () => { + let tryAgain = document.getElementById("tryAgain"); + let sendCrashReport = document.getElementById("checkSendReport"); + + tryAgain.addEventListener("click", () => { + let event = new CustomEvent("AboutTabCrashedTryAgain", { + bubbles: true, + detail: { + sendCrashReport: sendCrashReport.checked, + }, + }); + + document.dispatchEvent(event); + }); +}); + // Error pages are loaded as LOAD_BACKGROUND, so they don't get load events. var event = new CustomEvent("AboutTabCrashedLoad", {bubbles:true}); document.dispatchEvent(event); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser-devedition.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser-devedition.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser-devedition.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser-devedition.js 2014-11-26 21:45:46.000000000 +0000 @@ -50,6 +50,17 @@ } }, + _inferBrightness: function() { + ToolbarIconColor.inferFromText(); + // Get an inverted full screen button if the dark theme is applied. + if (this.styleSheet && + document.documentElement.getAttribute("devtoolstheme") == "dark") { + document.documentElement.setAttribute("brighttitlebarforeground", "true"); + } else { + document.documentElement.removeAttribute("brighttitlebarforeground"); + } + }, + _updateDevtoolsThemeAttribute: function() { // Set an attribute on root element to make it possible // to change colors based on the selected devtools theme. @@ -58,7 +69,7 @@ devtoolsTheme = "light"; } document.documentElement.setAttribute("devtoolstheme", devtoolsTheme); - ToolbarIconColor.inferFromText(); + this._inferBrightness(); this._updateStyleSheetFromPrefs(); }, @@ -83,7 +94,7 @@ if (e.type === "load") { this.styleSheet.removeEventListener("load", this); gBrowser.tabContainer._positionPinnedTabs(); - ToolbarIconColor.inferFromText(); + this._inferBrightness(); Services.obs.notifyObservers(window, "devedition-theme-state-changed", true); } }, @@ -102,7 +113,7 @@ this.styleSheet.remove(); this.styleSheet = null; gBrowser.tabContainer._positionPinnedTabs(); - ToolbarIconColor.inferFromText(); + this._inferBrightness(); Services.obs.notifyObservers(window, "devedition-theme-state-changed", false); } }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser.js 2014-11-26 21:45:46.000000000 +0000 @@ -841,9 +841,9 @@ browser.userTypedClear++; } + let shouldBeRemote = gMultiProcessBrowser && + E10SUtils.shouldBrowserBeRemote(uri); try { - let shouldBeRemote = gMultiProcessBrowser && - E10SUtils.shouldBrowserBeRemote(uri); if (browser.isRemoteBrowser == shouldBeRemote) { browser.webNavigation.loadURI(uri, flags, referrer, postdata, null); } else { @@ -853,6 +853,13 @@ referrer: referrer ? referrer.spec : null, }); } + } catch (e) { + // If anything goes wrong just switch remoteness manually and load the URI. + // We might lose history that way but at least the browser loaded a page. + // This might be necessary if SessionStore wasn't initialized yet i.e. + // when the homepage is a non-remote page. + gBrowser.updateBrowserRemoteness(browser, shouldBeRemote); + browser.webNavigation.loadURI(uri, flags, referrer, postdata, null); } finally { if (browser.userTypedClear) { browser.userTypedClear--; @@ -1135,6 +1142,28 @@ #endif }, false, true); + gBrowser.addEventListener("AboutTabCrashedTryAgain", function(event) { + let ownerDoc = event.originalTarget; + + if (!ownerDoc.documentURI.startsWith("about:tabcrashed")) { + return; + } + + let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView); + if (!isTopFrame) { + return; + } + + let browser = gBrowser.getBrowserForDocument(ownerDoc); +#ifdef MOZ_CRASHREPORTER + if (event.detail.sendCrashReport) { + TabCrashReporter.submitCrashReport(browser); + } +#endif + let tab = gBrowser.getTabForBrowser(browser); + SessionStore.reviveCrashedTab(tab); + }, false, true); + if (uriToLoad && uriToLoad != "about:blank") { if (uriToLoad instanceof Ci.nsISupportsArray) { let count = uriToLoad.Count(); @@ -1736,7 +1765,7 @@ gBrowser.selectedBrowser); break; case "Save": - saveDocument(window.content.document); + saveDocument(gBrowser.selectedBrowser.contentDocumentAsCPOW); break; case "SendMail": MailIntegration.sendLinkForWindow(window.content); @@ -2599,9 +2628,6 @@ ownerDoc.documentURI.toLowerCase() == "about:newtab") { this.onE10sAboutNewTab(event, ownerDoc); } - else if (ownerDoc.documentURI.startsWith("about:tabcrashed")) { - this.onAboutTabCrashed(event, ownerDoc); - } }, receiveMessage: function (msg) { @@ -2862,29 +2888,6 @@ } }, - /** - * The about:tabcrashed can't do window.reload() because that - * would reload the page but not use a remote browser. - */ - onAboutTabCrashed: function(event, ownerDoc) { - let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView); - if (!isTopFrame) { - return; - } - - let button = event.originalTarget; - if (button.id == "tryAgain") { - let browser = gBrowser.getBrowserForDocument(ownerDoc); -#ifdef MOZ_CRASHREPORTER - if (ownerDoc.getElementById("checkSendReport").checked) { - TabCrashReporter.submitCrashReport(browser); - } -#endif - let tab = gBrowser.getTabForBrowser(browser); - SessionStore.reviveCrashedTab(tab); - } - }, - ignoreWarningButton: function (isMalware) { // Allow users to override and continue through to the site, // but add a notify bar as a reminder, so that they don't lose @@ -7302,9 +7305,13 @@ if (gURLBar && !PrivateBrowsingUtils.permanentPrivateBrowsing) { - // Disable switch to tab autocompletion for private windows - // (not for "Always use private browsing" mode) - gURLBar.setAttribute("autocompletesearchparam", ""); + // Disable switch to tab autocompletion for private windows. + // We leave it enabled for permanent private browsing mode though. + let value = gURLBar.getAttribute("autocompletesearchparam") || ""; + if (!value.contains("disable-private-actions")) { + gURLBar.setAttribute("autocompletesearchparam", + value + " disable-private-actions"); + } } } }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser-loop.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser-loop.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser-loop.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser-loop.js 2014-11-26 21:45:46.000000000 +0000 @@ -11,7 +11,6 @@ (function() { - LoopUI = { get toolbarButton() { delete this.toolbarButton; @@ -84,8 +83,28 @@ state = "active"; } else if (MozLoopService.doNotDisturb) { state = "disabled"; + } else if (MozLoopService.roomsParticipantsCount > 0) { + state = "active"; } this.toolbarButton.node.setAttribute("state", state); }, + + /** + * Play a sound in this window IF there's no sound playing yet. + * + * @param {String} name Name of the sound, like 'ringtone' or 'room-joined' + */ + playSound: function(name) { + if (this.ActiveSound || MozLoopService.doNotDisturb) { + return; + } + + this.activeSound = new window.Audio(); + this.activeSound.src = `chrome://browser/content/loop/shared/sounds/${name}.ogg`; + this.activeSound.load(); + this.activeSound.play(); + + this.activeSound.addEventListener("ended", () => this.activeSound = undefined, false); + }, }; })(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser-sets.inc thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser-sets.inc --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser-sets.inc 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser-sets.inc 2014-11-26 21:45:46.000000000 +0000 @@ -22,7 +22,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/browser.xul 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/browser.xul 2014-11-26 21:45:46.000000000 +0000 @@ -720,7 +720,6 @@ enablehistory="true" maxrows="6" newlines="stripsurroundingwhitespace" - oninput="gBrowser.userTypedValue = this.value;" ontextentered="this.handleCommand(param);" ontextreverted="return this.handleRevert();" pageproxystate="invalid" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/content.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/content.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/content.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/content.js 2014-11-26 21:45:46.000000000 +0000 @@ -87,41 +87,61 @@ LoginManagerContent.onUsernameInput(event); }); -if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) { - let handleContentContextMenu = function (event) { - let defaultPrevented = event.defaultPrevented; - if (!Services.prefs.getBoolPref("dom.event.contextmenu.enabled")) { - let plugin = null; - try { - plugin = event.target.QueryInterface(Ci.nsIObjectLoadingContent); - } catch (e) {} - if (plugin && plugin.displayedType == Ci.nsIObjectLoadingContent.TYPE_PLUGIN) { - // Don't open a context menu for plugins. - return; - } - - defaultPrevented = false; +let handleContentContextMenu = function (event) { + let defaultPrevented = event.defaultPrevented; + if (!Services.prefs.getBoolPref("dom.event.contextmenu.enabled")) { + let plugin = null; + try { + plugin = event.target.QueryInterface(Ci.nsIObjectLoadingContent); + } catch (e) {} + if (plugin && plugin.displayedType == Ci.nsIObjectLoadingContent.TYPE_PLUGIN) { + // Don't open a context menu for plugins. + return; } - if (!defaultPrevented) { - let editFlags = SpellCheckHelper.isEditable(event.target, content); - let spellInfo; - if (editFlags & - (SpellCheckHelper.EDITABLE | SpellCheckHelper.CONTENTEDITABLE)) { - spellInfo = - InlineSpellCheckerContent.initContextMenu(event, editFlags, this); - } - - sendSyncMessage("contextmenu", { editFlags, spellInfo }, { event }); - } + defaultPrevented = false; } - Cc["@mozilla.org/eventlistenerservice;1"] - .getService(Ci.nsIEventListenerService) - .addSystemEventListener(global, "contextmenu", handleContentContextMenu, true); + if (defaultPrevented) + return; + + let addonInfo = {}; + let subject = { + event: event, + addonInfo: addonInfo, + }; + subject.wrappedJSObject = subject; + Services.obs.notifyObservers(subject, "content-contextmenu", null); + + if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) { + let editFlags = SpellCheckHelper.isEditable(event.target, content); + let spellInfo; + if (editFlags & + (SpellCheckHelper.EDITABLE | SpellCheckHelper.CONTENTEDITABLE)) { + spellInfo = + InlineSpellCheckerContent.initContextMenu(event, editFlags, this); + } + sendSyncMessage("contextmenu", { editFlags, spellInfo, addonInfo }, { event, popupNode: event.target }); + } + else { + // Break out to the parent window and pass the add-on info along + let browser = docShell.chromeEventHandler; + let mainWin = browser.ownerDocument.defaultView; + mainWin.gContextMenuContentData = { + isRemote: false, + event: event, + popupNode: event.target, + browser: browser, + addonInfo: addonInfo, + }; + } } +Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService) + .addSystemEventListener(global, "contextmenu", handleContentContextMenu, false); + let AboutNetErrorListener = { init: function(chromeGlobal) { chromeGlobal.addEventListener('AboutNetErrorLoad', this, false, true); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/nsContextMenu.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/nsContextMenu.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/nsContextMenu.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/nsContextMenu.js 2014-11-26 21:45:46.000000000 +0000 @@ -528,17 +528,16 @@ // Set various context menu attributes based on the state of the world. setTarget: function (aNode, aRangeParent, aRangeOffset) { - // If gContextMenuContentData is not null, this event was forwarded from a - // child process, so use that information instead. + // gContextMenuContentData.isRemote tells us if the event came from a remote + // process. gContextMenuContentData can be null if something (like tests) + // opens the context menu directly. let editFlags; - if (gContextMenuContentData) { - this.isRemote = true; + this.isRemote = gContextMenuContentData && gContextMenuContentData.isRemote; + if (this.isRemote) { aNode = gContextMenuContentData.event.target; aRangeParent = gContextMenuContentData.event.rangeParent; aRangeOffset = gContextMenuContentData.event.rangeOffset; editFlags = gContextMenuContentData.editFlags; - } else { - this.isRemote = false; } const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; @@ -628,7 +627,10 @@ this.onCanvas = true; } else if (this.target instanceof HTMLVideoElement) { - this.mediaURL = this.target.currentSrc || this.target.src; + let mediaURL = this.target.currentSrc || this.target.src; + if (this.isMediaURLReusable(mediaURL)) { + this.mediaURL = mediaURL; + } // Firefox always creates a HTMLVideoElement when loading an ogg file // directly. If the media is actually audio, be smarter and provide a // context menu with audio operations. @@ -641,13 +643,16 @@ } else if (this.target instanceof HTMLAudioElement) { this.onAudio = true; - this.mediaURL = this.target.currentSrc || this.target.src; + let mediaURL = this.target.currentSrc || this.target.src; + if (this.isMediaURLReusable(mediaURL)) { + this.mediaURL = mediaURL; + } } else if (editFlags & (SpellCheckHelper.INPUT | SpellCheckHelper.TEXTAREA)) { this.onTextInput = (editFlags & SpellCheckHelper.TEXTINPUT) !== 0; this.onEditableArea = (editFlags & SpellCheckHelper.EDITABLE) !== 0; if (this.onEditableArea) { - if (gContextMenuContentData) { + if (this.isRemote) { InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo); } else { @@ -772,7 +777,7 @@ this.hasBGImage = false; this.isDesignMode = true; this.onEditableArea = true; - if (gContextMenuContentData) { + if (this.isRemote) { InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo); } else { @@ -1505,6 +1510,10 @@ return !this.focusedWindow.getSelection().isCollapsed; }, + isMediaURLReusable: function(aURL) { + return !/^(?:blob|mediasource):/.test(aURL); + }, + toString: function () { return "contextMenu.target = " + this.target + "\n" + "contextMenu.onImage = " + this.onImage + "\n" + @@ -1764,31 +1773,18 @@ }, _getTelemetryPageContextInfo: function() { - if (this.isContentSelected) { - return "selection"; - } - if (this.onLink) { - if (this.onImage || this.onCanvas) { - return "image-link"; + let rv = []; + for (let k of ["isContentSelected", "onLink", "onImage", "onCanvas", "onVideo", "onAudio", + "onTextInput", "onSocial"]) { + if (this[k]) { + rv.push(k.replace(/^(?:is|on)(.)/, (match, firstLetter) => firstLetter.toLowerCase())); } - return "link"; } - if (this.onImage) { - return "image" + if (!rv.length) { + rv.push('other'); } - if (this.onCanvas) { - return "canvas"; - } - if (this.onVideo || this.onAudio) { - return "media"; - } - if (this.onTextInput) { - return "input"; - } - if (this.onSocial) { - return "social"; - } - return "other"; + + return JSON.stringify(rv); }, _checkTelemetryForMenu: function(aXulMenu) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/socialchat.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/socialchat.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/socialchat.xml 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/socialchat.xml 2014-11-26 21:45:46.000000000 +0000 @@ -193,6 +193,9 @@ () => { this.swapDocShells(cb); + chatbar.focus(); + this.close(); + // chatboxForURL is a map of URL -> chatbox used to avoid opening // duplicate chat windows. Ensure reattached chat windows aren't // registered with about:blank as their URL, otherwise reattaching @@ -200,8 +203,6 @@ chatbar.chatboxForURL.delete("about:blank"); chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb)); - chatbar.focus(); - this.close(); deferred.resolve(cb); } ); @@ -527,7 +528,9 @@ let cb = this.chatboxForURL.get(aURL); if (cb) { cb = cb.get(); - if (cb.parentNode) { + // A chatbox is still alive to us when it's parented and still has + // content. + if (cb.parentNode && cb.contentWindow) { this.showChat(cb, aMode); if (aCallback) { if (cb._callbacks == null) { @@ -646,6 +649,7 @@ @@ -3084,10 +3082,13 @@ let spellInfo = aMessage.data.spellInfo; if (spellInfo) spellInfo.target = aMessage.target.messageManager; - gContextMenuContentData = { event: aMessage.objects.event, + gContextMenuContentData = { isRemote: true, + event: aMessage.objects.event, + popupNode: aMessage.objects.popupNode, browser: browser, editFlags: aMessage.data.editFlags, - spellInfo: spellInfo }; + spellInfo: spellInfo, + addonInfo: aMessage.data.addonInfo }; let popup = browser.ownerDocument.getElementById("contentAreaContextMenu"); let event = gContextMenuContentData.event; let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY); @@ -3464,7 +3465,7 @@ return; var tab = this._getTabForContentWindow(contentWin); - if (tab.hasAttribute("pending")) + if (!tab || tab.hasAttribute("pending")) return; var titleChanged = this.setTabTitle(tab); @@ -5368,7 +5369,10 @@ }, () => { // If the promise rejected, that means we don't want to actually // flip the deck, so we cancel the tab switch. - gBrowser._cancelTabSwitch(toTab); + // We need to nullcheck the method we're about to call because + // the binding might be dead at this point. + if (gBrowser._cancelTabSwitch) + gBrowser._cancelTabSwitch(toTab); }); return val; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_action_searchengine.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_action_searchengine.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_action_searchengine.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_action_searchengine.js 2014-11-26 21:45:47.000000000 +0000 @@ -43,11 +43,14 @@ let result = yield promise_first_result("open a search"); isnot(result, null, "Should have a result"); + is(result.getAttribute("url"), + `moz-action:searchengine,{"engineName":"MozSearch","input":"open a search","searchQuery":"open a search"}`, + "Result should be a moz-action: for the correct search engine"); is(result.hasAttribute("image"), false, "Result shouldn't have an image attribute"); let tabPromise = promiseTabLoaded(gBrowser.selectedTab); EventUtils.synthesizeMouseAtCenter(result, {}); yield tabPromise; - is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search"); + is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search", "Correct URL should be loaded"); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_alltabslistener.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_alltabslistener.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_alltabslistener.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_alltabslistener.js 2014-11-26 21:45:47.000000000 +0000 @@ -94,7 +94,11 @@ // We must wait until the about:blank page has completed loading before // starting tests or we get notifications from that - gForegroundBrowser.addEventListener("load", startTests, true); + let promises = [ + waitForDocLoadComplete(gBackgroundBrowser), + waitForDocLoadComplete(gForegroundBrowser) + ]; + Promise.all(promises).then(startTest1); } function runTest(browser, url, next) { @@ -105,11 +109,6 @@ browser.loadURI(url); } -function startTests() { - gForegroundBrowser.removeEventListener("load", startTests, true); - executeSoon(startTest1); -} - function startTest1() { info("\nTest 1"); gBrowser.addProgressListener(gFrontProgressListener); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_autocomplete_autoselect.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_autocomplete_autoselect.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_autocomplete_autoselect.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_autocomplete_autoselect.js 2014-11-26 21:45:47.000000000 +0000 @@ -0,0 +1,59 @@ +function repeat(limit, func) { + for (let i = 0; i < limit; i++) { + func(i); + } +} + +function* promiseAutoComplete(inputText) { + gURLBar.focus(); + gURLBar.value = inputText.slice(0, -1); + EventUtils.synthesizeKey(inputText.slice(-1), {}); + yield promiseSearchComplete(); +} + +function is_selected(index) { + is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`); +} + +add_task(function*() { + registerCleanupFunction(promiseClearHistory); + + let visits = []; + repeat(10, i => { + visits.push({ + uri: makeURI("http://example.com/autocomplete/?" + i), + }); + }); + yield PlacesTestUtils.addVisits(visits); + + yield promiseAutoComplete("example.com/autocomplete"); + + let popup = gURLBar.popup; + let results = popup.richlistbox.children; + // 1 extra for the current search engine match + is(results.length, 11, "Should get 11 results"); + is_selected(0); + + info("Key Down to select the next item"); + EventUtils.synthesizeKey("VK_DOWN", {}); + is_selected(1); + + info("Key Down 11 times should wrap around all the way around"); + repeat(11, () => EventUtils.synthesizeKey("VK_DOWN", {})); + is_selected(1); + + info("Key Up 11 times should wrap around the other way"); + repeat(11, () => EventUtils.synthesizeKey("VK_UP", {})); + is_selected(1); + + info("Page Up will go up the list, but not wrap"); + EventUtils.synthesizeKey("VK_PAGE_UP", {}) + is_selected(0); + + info("Page Up again will wrap around to the end of the list"); + EventUtils.synthesizeKey("VK_PAGE_UP", {}) + is_selected(10); + + EventUtils.synthesizeKey("VK_ESCAPE", {}); + yield promisePopupHidden(gURLBar.popup); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_autocomplete_no_title.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_autocomplete_no_title.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_autocomplete_no_title.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_autocomplete_no_title.js 2014-11-26 21:45:47.000000000 +0000 @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function* check_title(inputText, expectedTitle) { + gURLBar.focus(); + gURLBar.value = inputText.slice(0, -1); + EventUtils.synthesizeKey(inputText.slice(-1) , {}); + yield promiseSearchComplete(); + + ok(gURLBar.popup.richlistbox.children.length > 1, "Should get at least 2 results"); + let result = gURLBar.popup.richlistbox.children[1]; + is(result._title.textContent, expectedTitle, "Result title should be as expected"); +} + +add_task(function*() { + // This test is only relevant if UnifiedComplete is enabled. + if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) + return; + + let uri = NetUtil.newURI("http://bug1060642.example.com/beards/are/pretty/great"); + yield PlacesTestUtils.addVisits([{uri: uri, title: ""}]); + + yield check_title("bug1060642", "bug1060642.example.com"); + + gURLBar.popup.hidePopup(); + yield promisePopupHidden(gURLBar.popup); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug1003461-switchtab-override.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug1003461-switchtab-override.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug1003461-switchtab-override.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug1003461-switchtab-override.js 2014-11-26 21:45:47.000000000 +0000 @@ -35,7 +35,7 @@ onSearchComplete.apply(gURLBar); deferred.resolve(); } - + gURLBar.focus(); gURLBar.value = "dummy_pag"; EventUtils.synthesizeKey("e" , {}); @@ -43,7 +43,6 @@ info("Select second autocomplete popup entry"); EventUtils.synthesizeKey("VK_DOWN" , {}); - EventUtils.synthesizeKey("VK_DOWN" , {}); ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found"); info("Override switch-to-tab"); @@ -61,6 +60,7 @@ EventUtils.synthesizeKey("VK_SHIFT" , { type: "keydown" }); EventUtils.synthesizeKey("VK_RETURN" , { }); + info(`gURLBar.value = ${gURLBar.value}`); EventUtils.synthesizeKey("VK_SHIFT" , { type: "keyup" }); yield deferred.promise; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js 2014-11-26 21:45:47.000000000 +0000 @@ -21,26 +21,13 @@ return promiseClearHistory(); }); - info("Wait for autocomplete") - let searchDeferred = Promise.defer(); - let onSearchComplete = gURLBar.onSearchComplete; - registerCleanupFunction(() => { - gURLBar.onSearchComplete = onSearchComplete; - }); - gURLBar.onSearchComplete = function () { - ok(gURLBar.popupOpen, "The autocomplete popup is correctly open"); - onSearchComplete.apply(gURLBar); - searchDeferred.resolve(); - } - gURLBar.focus(); gURLBar.value = "dummy_pag"; EventUtils.synthesizeKey("e" , {}); - yield searchDeferred.promise; + yield promiseSearchComplete(); info("Select second autocomplete popup entry"); EventUtils.synthesizeKey("VK_DOWN" , {}); - EventUtils.synthesizeKey("VK_DOWN" , {}); ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found"); info("Shift+left on switch-to-tab entry"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug1070778.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug1070778.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug1070778.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug1070778.js 2014-11-26 21:45:47.000000000 +0000 @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function* promiseAutoComplete(inputText) { + gURLBar.focus(); + gURLBar.value = inputText.slice(0, -1); + EventUtils.synthesizeKey(inputText.slice(-1) , {}); + yield promiseSearchComplete(); +} + +function is_selected(index) { + is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`); +} + +add_task(function*() { + // This test is only relevant if UnifiedComplete is enabled. + if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete")) + return; + + registerCleanupFunction(() => { + PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); + }); + + let itemId = + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + NetUtil.newURI("http://example.com/?q=%s"), + PlacesUtils.bookmarks.DEFAULT_INDEX, + "test"); + PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword"); + + // This item only needed so we can select the keyword item, select something + // else, then select the keyword item again. + itemId = + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + NetUtil.newURI("http://example.com/keyword"), + PlacesUtils.bookmarks.DEFAULT_INDEX, + "keyword abc"); + + yield promiseAutoComplete("keyword a"); + + // First item should already be selected + is_selected(0); + // Select next one (important!) + EventUtils.synthesizeKey("VK_DOWN", {}); + is_selected(1); + // Re-select keyword item + EventUtils.synthesizeKey("VK_UP", {}); + is_selected(0); + + EventUtils.synthesizeKey("b", {}); + yield promiseSearchComplete(); + + is(gURLBar.value, "keyword ab", "urlbar should have expected input"); + + let result = gURLBar.popup.richlistbox.firstChild; + isnot(result, null, "Should have first item"); + let uri = NetUtil.newURI(result.getAttribute("url")); + is(uri.spec, makeActionURI("keyword", {url: "http://example.com/?q=ab", input: "keyword ab"}).spec, "Expect correct url"); + + EventUtils.synthesizeKey("VK_ESCAPE", {}); + yield promisePopupHidden(gURLBar.popup); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug304198.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug304198.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug304198.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug304198.js 2014-11-26 21:45:47.000000000 +0000 @@ -21,16 +21,15 @@ function cycleTabs() { gBrowser.selectedTab = fullURLTab; - is(gURLBar.value, testURL, 'gURLBar.value should be testURL after switching back to fullURLTab'); + is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after switching back to fullURLTab'); gBrowser.selectedTab = partialURLTab; - is(gURLBar.value, testPartialURL, 'gURLBar.value should be testPartialURL after switching back to partialURLTab'); - + is(gURLBar.textValue, testPartialURL, 'gURLBar.textValue should be testPartialURL after switching back to partialURLTab'); gBrowser.selectedTab = deletedURLTab; - is(gURLBar.value, '', 'gURLBar.value should be "" after switching back to deletedURLTab'); + is(gURLBar.textValue, '', 'gURLBar.textValue should be "" after switching back to deletedURLTab'); gBrowser.selectedTab = fullURLTab; - is(gURLBar.value, testURL, 'gURLBar.value should be testURL after switching back to fullURLTab'); + is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after switching back to fullURLTab'); } // function borrowed from browser_bug386835.js @@ -59,13 +58,13 @@ function prepareDeletedURLTab(cb) { gBrowser.selectedTab = deletedURLTab; - is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to deletedURLTab'); + is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after initial switch to deletedURLTab'); // simulate the user removing the whole url from the location bar gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", true); urlbarBackspace(function () { - is(gURLBar.value, "", 'gURLBar.value should be "" (just set)'); + is(gURLBar.textValue, "", 'gURLBar.textValue should be "" (just set)'); if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll")) gPrefService.clearUserPref("browser.urlbar.clickSelectsAll"); cb(); @@ -74,13 +73,13 @@ function prepareFullURLTab(cb) { gBrowser.selectedTab = fullURLTab; - is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to fullURLTab'); + is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after initial switch to fullURLTab'); cb(); } function preparePartialURLTab(cb) { gBrowser.selectedTab = partialURLTab; - is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to partialURLTab'); + is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after initial switch to partialURLTab'); // simulate the user removing part of the url from the location bar gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", false); @@ -91,7 +90,7 @@ if (deleted < charsToDelete) { urlbarBackspace(arguments.callee); } else { - is(gURLBar.value, testPartialURL, "gURLBar.value should be testPartialURL (just set)"); + is(gURLBar.textValue, testPartialURL, "gURLBar.textValue should be testPartialURL (just set)"); if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll")) gPrefService.clearUserPref("browser.urlbar.clickSelectsAll"); cb(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug481560.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug481560.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug481560.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug481560.js 2014-11-26 21:45:47.000000000 +0000 @@ -1,14 +1,8 @@ function test() { waitForExplicitFinish(); - var win = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no"); - - win.addEventListener("load", function () { - win.removeEventListener("load", arguments.callee, false); - - win.content.addEventListener("focus", function () { - win.content.removeEventListener("focus", arguments.callee, false); - + whenNewWindowLoaded(null, function (win) { + waitForFocus(function () { function onTabClose() { ok(false, "shouldn't have gotten the TabClose event for the last tab"); } @@ -22,6 +16,6 @@ tab.removeEventListener("TabClose", onTabClose, false); finish(); - }, false); - }, false); + }, win); + }); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug556061.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug556061.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug556061.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug556061.js 2014-11-26 21:45:47.000000000 +0000 @@ -31,7 +31,8 @@ setup: function() { gURLBar.value = testActionURL; gURLBar.valueIsTyped = true; - is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value"); + is(gURLBar.value, testActionURL, "gURLBar starts with the correct real value"); + is(gURLBar.textValue, testURL, "gURLBar starts with the correct display value"); // Focus the urlbar so we can select it all & copy gURLBar.focus(); @@ -73,7 +74,8 @@ gURLBar.value = testActionURL; gURLBar.valueIsTyped = true; // Sanity check that we have the right value - is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value"); + is(gURLBar.value, testActionURL, "gURLBar starts with the correct real value"); + is(gURLBar.textValue, testURL, "gURLBar starts with the correct display value"); // Now just select part of the value & cut that. gURLBar.selectionStart = testURL.length - 10; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug633691.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug633691.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug633691.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug633691.js 2014-11-26 21:45:47.000000000 +0000 @@ -6,12 +6,15 @@ waitForExplicitFinish(); gBrowser.selectedTab = gBrowser.addTab(); // Open a html page with about:certerror in an iframe - window.content.addEventListener("load", testIframeCert, true); + gBrowser.selectedBrowser.addEventListener("load", testIframeCert, true); content.location = "data:text/html,"; } -function testIframeCert() { - window.content.removeEventListener("load", testIframeCert, true); +function testIframeCert(e) { + if (e.target.location.href == "about:blank") { + return; + } + gBrowser.selectedBrowser.removeEventListener("load", testIframeCert, true); // Confirm that the expert section is hidden var doc = gBrowser.contentDocument.getElementsByTagName('iframe')[0].contentDocument; var eC = doc.getElementById("expertContent"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug816527.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug816527.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug816527.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug816527.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -/* 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/. */ - -function test() { - waitForExplicitFinish(); - - let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html"; - - function testOnWindow(aOptions, aCallback) { - whenNewWindowLoaded(aOptions, function(aWin) { - // execute should only be called when need, like when you are opening - // web pages on the test. If calling executeSoon() is not necesary, then - // call whenNewWindowLoaded() instead of testOnWindow() on your test. - executeSoon(function() aCallback(aWin)); - }); - }; - - testOnWindow({}, function(aNormalWindow) { - testOnWindow({private: true}, function(aPrivateWindow) { - runTest(aNormalWindow, aPrivateWindow, false, function() { - aNormalWindow.close(); - aPrivateWindow.close(); - testOnWindow({}, function(aNormalWindow) { - testOnWindow({private: true}, function(aPrivateWindow) { - runTest(aPrivateWindow, aNormalWindow, false, function() { - aNormalWindow.close(); - aPrivateWindow.close(); - testOnWindow({private: true}, function(aPrivateWindow) { - runTest(aPrivateWindow, aPrivateWindow, false, function() { - aPrivateWindow.close(); - testOnWindow({}, function(aNormalWindow) { - runTest(aNormalWindow, aNormalWindow, true, function() { - aNormalWindow.close(); - finish(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - function runTest(aSourceWindow, aDestWindow, aExpectSuccess, aCallback) { - // Open the base tab - let baseTab = aSourceWindow.gBrowser.addTab(testURL); - baseTab.linkedBrowser.addEventListener("load", function() { - // Wait for the tab to be fully loaded so matching happens correctly - if (baseTab.linkedBrowser.currentURI.spec == "about:blank") - return; - baseTab.linkedBrowser.removeEventListener("load", arguments.callee, true); - - let testTab = aDestWindow.gBrowser.addTab(); - - waitForFocus(function() { - // Select the testTab - aDestWindow.gBrowser.selectedTab = testTab; - - // Ensure that this tab has no history entries - ok(testTab.linkedBrowser.sessionHistory.count < 2, - "The test tab has 1 or less history entries"); - // Ensure that this tab is on about:blank - is(testTab.linkedBrowser.currentURI.spec, "about:blank", - "The test tab is on about:blank"); - // Ensure that this tab's document has no child nodes - ok(!testTab.linkedBrowser.contentDocument.body.hasChildNodes(), - "The test tab has no child nodes"); - ok(!testTab.hasAttribute("busy"), - "The test tab doesn't have the busy attribute"); - - // Set the urlbar to include the moz-action - aDestWindow.gURLBar.value = "moz-action:switchtab," + JSON.stringify({url: testURL}); - // Focus the urlbar so we can press enter - aDestWindow.gURLBar.focus(); - - // We want to see if the switchtab action works. If it does, the - // current tab will get closed, and that's what we detect with the - // TabClose handler. If pressing enter triggers a load in that tab, - // then the load handler will get called. Neither of these are - // the desired effect here. So if the test goes successfully, it is - // the timeout handler which gets called. - // - // The reason that we can't avoid the timeout here is because we are - // trying to test something which should not happen, so we just need - // to wait for a while and then check whether any bad things have - // happened. - - function onTabClose(aEvent) { - aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false); - aDestWindow.gBrowser.removeEventListener("load", onLoad, false); - clearTimeout(timeout); - // Should only happen when we expect success - ok(aExpectSuccess, "Tab closed as expected"); - aCallback(); - } - function onLoad(aEvent) { - aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false); - aDestWindow.gBrowser.removeEventListener("load", onLoad, false); - clearTimeout(timeout); - // Should only happen when we expect success - ok(aExpectSuccess, "Tab loaded as expected"); - aCallback(); - } - - aDestWindow.gBrowser.tabContainer.addEventListener("TabClose", onTabClose, false); - aDestWindow.gBrowser.addEventListener("load", onLoad, false); - let timeout = setTimeout(function() { - aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false); - aDestWindow.gBrowser.removeEventListener("load", onLoad, false); - aCallback(); - }, 500); - - // Press enter! - EventUtils.synthesizeKey("VK_RETURN", {}); - }, aDestWindow); - }, true); - } -} - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug906190.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug906190.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_bug906190.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_bug906190.js 2014-11-26 21:45:47.000000000 +0000 @@ -98,7 +98,7 @@ let clickHandler = function (aEvent, aFunc) { gTestWin.gBrowser.removeEventListener("click", curClickHandler, true); gTestWin.contentAreaClick(aEvent, true); - gTestWin.gBrowser.addEventListener("load", aFunc, true); + waitForSomeTabToLoad(aFunc); aEvent.preventDefault(); aEvent.stopPropagation(); } @@ -108,7 +108,7 @@ // from the contextmenu which dispatches to the function openLinkInTab. let contextMenuOpenHandler = function(aEvent, aFunc) { gTestWin.document.removeEventListener("popupshown", curContextMenu, false); - gTestWin.gBrowser.addEventListener("load", aFunc, true); + waitForSomeTabToLoad(aFunc); var openLinkInTabCommand = gTestWin.document.getElementById("context-openlinkintab"); openLinkInTabCommand.doCommand(); aEvent.target.hidePopup(); @@ -124,12 +124,24 @@ let target = gTestWin.content.document.getElementById(aIDForNextTest); gTestWin.gBrowser.addTab(target); gTestWin.gBrowser.selectTabAtIndex(1); - gTestWin.gBrowser.addEventListener("load", checkPopUpNotification, true); + waitForSomeTabToLoad(checkPopUpNotification); +} + +// Waits for a load event somewhere in the browser but ignore events coming +// from s without a tab assigned. That are most likely browsers +// that preload the new tab page. +function waitForSomeTabToLoad(callback) { + gTestWin.gBrowser.addEventListener("load", function onLoad(event) { + let tab = gTestWin.gBrowser._getTabForContentWindow(event.target.defaultView.top); + if (tab) { + gTestWin.gBrowser.removeEventListener("load", onLoad, true); + callback(); + } + }, true); } function checkPopUpNotification() { - gTestWin.gBrowser.removeEventListener("load", checkPopUpNotification, true); - gTestWin.gBrowser.addEventListener("load", reloadedTabAfterDisablingMCB, true); + waitForSomeTabToLoad(reloadedTabAfterDisablingMCB); var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser); ok(notification, "OK: Mixed Content Doorhanger did appear in " + curTestName + "!"); @@ -142,8 +154,6 @@ } function reloadedTabAfterDisablingMCB() { - gTestWin.gBrowser.removeEventListener("load", reloadedTabAfterDisablingMCB, true); - var expected = "Mixed Content Blocker disabled"; waitForCondition( function() gTestWin.content.document.getElementById('mctestdiv').innerHTML == expected, @@ -177,7 +187,6 @@ } function test1A() { - gTestWin.gBrowser.removeEventListener("load", test1A, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true, @@ -206,7 +215,6 @@ } function test1C() { - gTestWin.gBrowser.removeEventListener("load", test1C, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true, @@ -241,7 +249,6 @@ } function test2A() { - gTestWin.gBrowser.removeEventListener("load", test2A, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<, @@ -270,7 +277,6 @@ } function test2C() { - gTestWin.gBrowser.removeEventListener("load", test2C, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<, @@ -306,12 +312,10 @@ function test3A() { // we need this indirection because the page is reloaded caused by meta-refresh - gTestWin.gBrowser.removeEventListener("load", test3A, true); - gTestWin.gBrowser.addEventListener("load", test3B, true); + waitForSomeTabToLoad(test3B); } function test3B() { - gTestWin.gBrowser.removeEventListener("load", test3B, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true! @@ -340,12 +344,10 @@ function test3D() { // we need this indirection because the page is reloaded caused by meta-refresh - gTestWin.gBrowser.removeEventListener("load", test3D, true); - gTestWin.gBrowser.addEventListener("load", test3E, true); + waitForSomeTabToLoad(test3E); } function test3E() { - gTestWin.gBrowser.removeEventListener("load", test3E, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true! @@ -380,12 +382,10 @@ function test4A() { // we need this indirection because the page is reloaded caused by meta-refresh - gTestWin.gBrowser.removeEventListener("load", test4A, true); - gTestWin.gBrowser.addEventListener("load", test4B, true); + waitForSomeTabToLoad(test4B); } function test4B() { - gTestWin.gBrowser.removeEventListener("load", test4B, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear and isMixedContentBlocked should be >> TRUE << @@ -414,12 +414,10 @@ function test4D() { // we need this indirection because the page is reloaded caused by meta-refresh - gTestWin.gBrowser.removeEventListener("load", test4D, true); - gTestWin.gBrowser.addEventListener("load", test4E, true); + waitForSomeTabToLoad(test4E); } function test4E() { - gTestWin.gBrowser.removeEventListener("load", test4E, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear and isMixedContentBlocked should be >> TRUE << @@ -454,7 +452,6 @@ } function test5A() { - gTestWin.gBrowser.removeEventListener("load", test5A, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true @@ -483,7 +480,6 @@ } function test5C() { - gTestWin.gBrowser.removeEventListener("load", test5C, true); // move the tab again gTestWin.gBrowser.selectTabAtIndex(2); @@ -520,7 +516,6 @@ } function test6A() { - gTestWin.gBrowser.removeEventListener("load", test6A, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear and isMixedContentBlocked should be >> TRUE << @@ -548,7 +543,6 @@ } function test6C() { - gTestWin.gBrowser.removeEventListener("load", test6C, true); gTestWin.gBrowser.selectTabAtIndex(2); // The Doorhanger should appear and isMixedContentBlocked should be >> TRUE << diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_canonizeURL.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_canonizeURL.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_canonizeURL.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_canonizeURL.js 2014-11-26 21:45:47.000000000 +0000 @@ -45,10 +45,12 @@ gURLBar.addEventListener("focus", function onFocus() { gURLBar.removeEventListener("focus", onFocus); + gURLBar.inputField.value = inputValue.slice(0, -1); + EventUtils.synthesizeKey(inputValue.slice(-1) , {}); EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true }); }); gBrowser.selectedBrowser.focus(); - gURLBar.inputField.value = inputValue; gURLBar.focus(); + } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_devedition.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_devedition.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_devedition.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_devedition.js 2014-11-26 21:45:47.000000000 +0000 @@ -16,12 +16,7 @@ Services.prefs.clearUserPref(PREF_DEVTOOLS_THEME); }); -function test() { - waitForExplicitFinish(); - startTests(); -} - -function startTests() { +add_task(function* startTests() { Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark"); info ("Setting browser.devedition.theme.enabled to false."); @@ -37,40 +32,54 @@ ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed when a lightweight theme is applied."); info ("Removing a lightweight theme."); + let onAttributeAdded = waitForBrightTitlebarAttribute(); Services.prefs.setBoolPref(PREF_LWTHEME, false); ok (DevEdition.styleSheet, "The devedition stylesheet has been added when a lightweight theme is removed."); + yield onAttributeAdded; + + is (document.documentElement.getAttribute("brighttitlebarforeground"), "true", + "The brighttitlebarforeground attribute is set on the window."); info ("Setting browser.devedition.theme.enabled to false."); Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, false); ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed."); - testDevtoolsTheme(); - testLightweightThemePreview(); - finish(); -} + ok (!document.documentElement.hasAttribute("brighttitlebarforeground"), + "The brighttitlebarforeground attribute is not set on the window after devedition.theme is false."); +}); -function testDevtoolsTheme() { +add_task(function* testDevtoolsTheme() { info ("Checking that Australis is shown when the light devtools theme is applied."); + let onAttributeAdded = waitForBrightTitlebarAttribute(); Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true); ok (DevEdition.styleSheet, "The devedition stylesheet exists."); + yield onAttributeAdded; + ok (document.documentElement.hasAttribute("brighttitlebarforeground"), + "The brighttitlebarforeground attribute is set on the window with dark devtools theme."); info ("Checking stylesheet and :root attributes based on devtools theme."); Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light"); is (document.documentElement.getAttribute("devtoolstheme"), "light", "The documentElement has an attribute based on devtools theme."); ok (DevEdition.styleSheet, "The devedition stylesheet is still there with the light devtools theme."); + ok (!document.documentElement.hasAttribute("brighttitlebarforeground"), + "The brighttitlebarforeground attribute is not set on the window with light devtools theme."); Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark"); is (document.documentElement.getAttribute("devtoolstheme"), "dark", "The documentElement has an attribute based on devtools theme."); ok (DevEdition.styleSheet, "The devedition stylesheet is still there with the dark devtools theme."); + is (document.documentElement.getAttribute("brighttitlebarforeground"), "true", + "The brighttitlebarforeground attribute is set on the window with dark devtools theme."); Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "foobar"); is (document.documentElement.getAttribute("devtoolstheme"), "light", "The documentElement has 'light' as a default for the devtoolstheme attribute"); ok (DevEdition.styleSheet, "The devedition stylesheet is still there with the foobar devtools theme."); -} + ok (!document.documentElement.hasAttribute("brighttitlebarforeground"), + "The brighttitlebarforeground attribute is not set on the window with light devtools theme."); +}); function dummyLightweightTheme(id) { return { @@ -83,7 +92,7 @@ }; } -function testLightweightThemePreview() { +add_task(function* testLightweightThemePreview() { let {LightweightThemeManager} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {}); info ("Turning the pref on, then previewing lightweight themes"); @@ -114,4 +123,21 @@ ok (DevEdition.styleSheet, "The devedition stylesheet is still enabled after the default theme is applied."); LightweightThemeManager.resetPreview(); ok (DevEdition.styleSheet, "The devedition stylesheet is still enabled after resetting the preview."); +}); + +// Use a mutation observer to wait for the brighttitlebarforeground +// attribute to change. Using this instead of waiting for the load +// event on the DevEdition styleSheet. +function waitForBrightTitlebarAttribute() { + return new Promise((resolve, reject) => { + let mutationObserver = new MutationObserver(function (mutations) { + for (let mutation of mutations) { + if (mutation.attributeName == "brighttitlebarforeground") { + mutationObserver.disconnect(); + resolve(); + } + } + }); + mutationObserver.observe(document.documentElement, { attributes: true }); + }); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser.ini 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser.ini 2014-11-26 21:45:47.000000000 +0000 @@ -120,11 +120,14 @@ [browser_search_favicon.js] skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s [browser_alltabslistener.js] -skip-if = os == "linux" || e10s # Linux: Intermittent failures, bug 951680; e10s: Bug 1093594 - notifications for tabs come in in the wrong order / unexpectedly [browser_autocomplete_a11y_label.js] -skip-if = e10s # Bug ????? - no e10s switch-to-tab support yet +skip-if = e10s # Bug 1101993 - times out for unknown reasons when run in the dir (works on its own) +[browser_autocomplete_no_title.js] +skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s +[browser_autocomplete_autoselect.js] +skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s [browser_backButtonFitts.js] -skip-if = os != "win" || e10s # The Fitts Law back button is only supported on Windows (bug 571454) / e10s - Bug ?????? test touches content (attempts to add an event listener directly to the contentWindow) +skip-if = os != "win" || e10s # The Fitts Law back button is only supported on Windows (bug 571454) / e10s - Bug 1099154: test touches content (attempts to add an event listener directly to the contentWindow) [browser_blob-channelname.js] [browser_bookmark_titles.js] skip-if = buildapp == 'mulet' || toolkit == "windows" || e10s # Disabled on Windows due to frequent failures (bugs 825739, 841341) / e10s - Bug 1094205 - places doesn't return the right thing in e10s mode, for some reason @@ -159,13 +162,12 @@ [browser_bug424101.js] skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode [browser_bug427559.js] -skip-if = e10s # Bug ?????? - "content window is focused - Got [object ChromeWindow], expected [object XrayWrapper [object Window]]" +skip-if = e10s # Bug 1102015 - "content window is focused - Got [object ChromeWindow], expected [object CPOW [object Window]]" [browser_bug431826.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (eg, var expertDiv = gBrowser.contentDocument.getElementById("expertContent");) [browser_bug432599.js] [browser_bug435035.js] [browser_bug435325.js] -skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content +skip-if = buildapp == 'mulet' || e10s # Bug 1099156 - test directly manipulates content [browser_bug441778.js] skip-if = buildapp == 'mulet' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s [browser_bug455852.js] @@ -173,7 +175,7 @@ [browser_bug460146.js] skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s [browser_bug462289.js] -skip-if = toolkit == "cocoa" || e10s # Bug ?????? - not sure why this is timing out and crashing!! +skip-if = toolkit == "cocoa" || e10s # Bug 1102017 - middle-button mousedown on selected tab2 does not activate tab - Didn't expect [object XULElement], but got it [browser_bug462673.js] skip-if = e10s # Bug 1093404 - test expects sync window opening from content and is disappointed in that expectation [browser_bug477014.js] @@ -181,7 +183,6 @@ [browser_bug479408.js] skip-if = buildapp == 'mulet' [browser_bug481560.js] -skip-if = e10s # Bug ????? - This bug attached an event listener directly to the content [browser_bug484315.js] skip-if = e10s [browser_bug491431.js] @@ -191,14 +192,13 @@ [browser_bug517902.js] skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s [browser_bug519216.js] -skip-if = e10s # Bug ?????? - some weird timing issue with progress listeners that fails intermittently [browser_bug520538.js] [browser_bug521216.js] [browser_bug533232.js] [browser_bug537013.js] skip-if = buildapp == 'mulet' || e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls replaceTabWithWindow) [browser_bug537474.js] -skip-if = e10s # Bug ?????? - test doesn't wait for document to be created before it checks it +skip-if = e10s # Bug 1102020 - test tries to use browserDOMWindow.openURI to open a link, and gets a null rv where it expects a window [browser_bug550565.js] [browser_bug553455.js] skip-if = true # Bug 1094312 @@ -227,7 +227,6 @@ skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s [browser_bug577121.js] [browser_bug578534.js] -skip-if = e10s # Bug ?????? - test directly manipulates content [browser_bug579872.js] [browser_bug580638.js] [browser_bug580956.js] @@ -250,11 +249,9 @@ [browser_bug597218.js] [browser_bug609700.js] [browser_bug623155.js] -skip-if = e10s # Bug ?????? - URLBar issues (apparently issues with redirection) [browser_bug623893.js] [browser_bug624734.js] [browser_bug633691.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (eg, var expertDiv = gBrowser.contentDocument.getElementById("expertContent");) [browser_bug647886.js] skip-if = buildapp == 'mulet' || e10s # Bug 1093373 - Relies on browser.sessionHistory [browser_bug655584.js] @@ -263,9 +260,9 @@ [browser_bug676619.js] skip-if = buildapp == 'mulet' || os == "mac" # mac: Intermittent failures, bug 925225 [browser_bug678392.js] -skip-if = e10s # Bug ?????? - Obscure non-windows failures ("Snapshot array has correct length of 1 after loading one page. - Got 0, expected 1" and more) +skip-if = e10s # bug 1102331 - does focus things on the content window which break in e10s mode [browser_bug710878.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (doc.querySelector) +skip-if = e10s # Bug 1100653 - test uses waitForFocus on content [browser_bug719271.js] skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s [browser_bug724239.js] @@ -277,12 +274,8 @@ [browser_bug763468_perwindowpb.js] skip-if = e10s [browser_bug767836_perwindowpb.js] -skip-if = e10s # Bug ?????? - test reports a leaked nsGlobalWindow with e10s enabled. [browser_bug771331.js] -skip-if = e10s # Bug ?????? - test directly manipulates content [browser_bug783614.js] -[browser_bug816527.js] -skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory [browser_bug817947.js] [browser_bug822367.js] [browser_bug832435.js] @@ -297,6 +290,8 @@ [browser_bug1015721.js] skip-if = os == 'win' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s [browser_bug1064280_changeUrlInPinnedTab.js] +[browser_bug1070778.js] +skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s [browser_canonizeURL.js] skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only [browser_contentAreaClick.js] @@ -304,7 +299,6 @@ [browser_contextSearchTabPosition.js] skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash [browser_ctrlTab.js] -skip-if = e10s # Bug ????? - thumbnail captures need e10s love (tabPreviews_capture fails with Argument 1 of CanvasRenderingContext2D.drawWindow does not implement interface Window.) [browser_customize_popupNotification.js] [browser_datareporting_notification.js] run-if = datareporting @@ -334,13 +328,11 @@ [browser_homeDrop.js] skip-if = buildapp == 'mulet' [browser_identity_UI.js] -skip-if = e10s # Bug ?????? - this test fails for obscure reasons on non-windows builds only. [browser_keywordBookmarklets.js] -skip-if = e10s # Bug ?????? - this test fails for obscure reasons on non-windows builds only. +skip-if = e10s # Bug 1102025 - different principals for the bookmarklet only in e10s mode (unclear if test or 'real' issue) [browser_keywordSearch.js] skip-if = e10s # Bug 921957 - remote webprogress doesn't supply cancel method on the request object [browser_keywordSearch_postData.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (gBrowser.contentDocument.body.textContent) [browser_lastAccessedTab.js] skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (bug 969405) [browser_locationBarCommand.js] @@ -352,17 +344,16 @@ [browser_middleMouse_noJSPaste.js] skip-if = e10s # Bug 921952 - Content:Click event issues [browser_minimize.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (TypeError: gBrowser.docShell is null) +skip-if = e10s # Bug 1100664 - test directly access content docShells (TypeError: gBrowser.docShell is null) [browser_mixedcontent_securityflags.js] [browser_notification_tab_switching.js] -skip-if = buildapp == 'mulet' || e10s # Bug ?????? - uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 +skip-if = buildapp == 'mulet' || e10s # Bug 1100662 - content access causing uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 (or in RemoteAddonsChild.jsm) [browser_offlineQuotaNotification.js] skip-if = buildapp == 'mulet' || e10s # Bug 1093603 - test breaks with PopupNotifications.panel.firstElementChild is null [browser_overflowScroll.js] [browser_pageInfo.js] skip-if = buildapp == 'mulet' || e10s # Bug 866413 - PageInfo doesn't work in e10s [browser_page_style_menu.js] -skip-if = e10s # Bug ?????? - test directly manipulates content [browser_parsable_css.js] skip-if = e10s @@ -373,10 +364,10 @@ [browser_plainTextLinks.js] skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode [browser_popupUI.js] -skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (tries to get a popup element directly from content) +skip-if = buildapp == 'mulet' || e10s # Bug 1100707 - test fails in e10s because it can't get accel-w to close the popup (?) [browser_popup_blocker.js] [browser_printpreview.js] -skip-if = buildapp == 'mulet' || e10s # Bug ?????? - timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost" +skip-if = buildapp == 'mulet' || e10s # Bug 1101973 - breaks the next test in e10s, and may be responsible for later timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost" [browser_private_browsing_window.js] skip-if = buildapp == 'mulet' [browser_private_no_prompt.js] @@ -402,11 +393,11 @@ # back to the clear recent history dialog (sanitize.xul), if # it ever is (bug 480169) [browser_save_link-perwindowpb.js] -skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (event.target) +skip-if = buildapp == 'mulet' || e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly [browser_save_private_link_perwindowpb.js] skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly [browser_save_video.js] -skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (event.target) +skip-if = buildapp == 'mulet' || e10s # Bug 1100698 - test uses synthesizeMouse and then does a load of other stuff that breaks in e10s [browser_save_video_frame.js] [browser_scope.js] [browser_searchSuggestionUI.js] @@ -415,14 +406,14 @@ searchSuggestionUI.html searchSuggestionUI.js [browser_selectTabAtIndex.js] -skip-if = e10s # Bug ?????? - no idea! "Accel+9 selects expected tab - Got 0, expected 9" [browser_star_hsts.js] -skip-if = e10s # Bug ?????? - timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost" [browser_subframe_favicons_not_used.js] [browser_tabDrop.js] skip-if = buildapp == 'mulet' || e10s -[browser_tabMatchesInAwesomebar_perwindowpb.js] +[browser_tabMatchesInAwesomebar.js] skip-if = e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls gBrowser.swapBrowsersAndCloseOther) +[browser_tabMatchesInAwesomebar_perwindowpb.js] +skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory [browser_tab_drag_drop_perwindow.js] skip-if = buildapp == 'mulet' [browser_tab_dragdrop.js] @@ -437,19 +428,17 @@ [browser_tabkeynavigation.js] skip-if = e10s [browser_tabopen_reflows.js] -skip-if = e10s # Bug ?????? - test needs to be updated for e10s (captures a stack that isn't correct in e10s) [browser_tabs_isActive.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (tries to get/set attributes directly on content docshell) +skip-if = e10s # Bug 1100664 - test relies on linkedBrowser.docShell [browser_tabs_owner.js] [browser_trackingUI.js] -skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode support-files = trackingPage.html benignPage.html [browser_typeAheadFind.js] skip-if = buildapp == 'mulet' || e10s # Bug 921935 - focusmanager issues with e10s (test calls waitForFocus) [browser_unloaddialogs.js] -skip-if = e10s # Bug ?????? - test uses chrome windowMediator to try and see alert() from content +skip-if = e10s # Bug 1100700 - test relies on unload event firing on closed tabs, which it doesn't [browser_urlHighlight.js] [browser_urlbarAutoFillTrimURLs.js] skip-if = e10s # Bug 1093941 - Waits indefinitely for onSearchComplete @@ -459,7 +448,6 @@ [browser_urlbarRevert.js] skip-if = e10s # Bug 1093941 - ESC reverted the location bar value - Got foobar, expected example.com [browser_urlbarSearchSingleWordNotification.js] -skip-if = e10s # Bug 1093997 - intermittent failures in e10s-mode only [browser_urlbarStop.js] skip-if = e10s # Bug 1093941 - test calls gBrowser.contentWindow.stop [browser_urlbarTrimURLs.js] @@ -479,7 +467,7 @@ [browser_windowopen_reflows.js] skip-if = buildapp == 'mulet' [browser_wyciwyg_urlbarCopying.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById) +skip-if = e10s # Bug 1100703 - test directly manipulates content (content.document.getElementById) [browser_zbug569342.js] skip-if = e10s # Bug 1094240 - has findbar-related failures [browser_registerProtocolHandler_notification.js] @@ -491,10 +479,10 @@ skip-if = e10s [browser_bug1025195_switchToTabHavingURI_ignoreFragment.js] [browser_addCertException.js] -skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById) +skip-if = e10s # Bug 1100687 - test directly manipulates content (content.document.getElementById) [browser_bug1045809.js] [browser_e10s_switchbrowser.js] [browser_blockHPKP.js] -skip-if = e10s # bug ?????? - test directly manipulates content (content.document.getElementById) +skip-if = e10s # bug 1100687 - test directly manipulates content (content.document.getElementById) [browser_mcb_redirect.js] skip-if = e10s # bug 1084504 - [e10s] Mixed content detection does not take redirection into account diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_locationBarCommand.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_locationBarCommand.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_locationBarCommand.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_locationBarCommand.js 2014-11-26 21:45:47.000000000 +0000 @@ -37,10 +37,10 @@ addPageShowListener(aWindow.gBrowser.selectedBrowser, function() { executeSoon(function () { info("URL should be loaded in a new window"); - is(gURLBar.value, "", "Urlbar reverted to original value"); + is(gURLBar.value, "", "Urlbar reverted to original value"); is(gFocusManager.focusedElement, null, "There should be no focused element"); is(gFocusManager.focusedWindow, aWindow.gBrowser.contentWindow, "Content window should be focused"); - is(aWindow.gURLBar.value, TEST_VALUE, "New URL is loaded in new window"); + is(aWindow.gURLBar.textValue, TEST_VALUE, "New URL is loaded in new window"); aWindow.close(); @@ -61,7 +61,7 @@ finish(); return; } - + info("Running test: " + test.desc); // Tab will be blank if test.startValue is null let tab = gBrowser.selectedTab = gBrowser.addTab(test.startValue); @@ -106,7 +106,7 @@ is(gURLBar.value, "", "Urlbar reverted to original value"); ok(!gURLBar.focused, "Urlbar is no longer focused after urlbar command"); is(gBrowser.selectedTab, aTab, "Focus did not change to the new tab"); - + // Select the new background tab gBrowser.selectedTab = gBrowser.selectedTab.nextSibling; is(gURLBar.value, TEST_VALUE, "New URL is loaded in new tab"); @@ -143,7 +143,7 @@ if (aClick) { is(gURLBar.getAttribute("pageproxystate"), "invalid", "page proxy state must be invalid for go button to be visible"); - EventUtils.synthesizeMouseAtCenter(gGoButton, aEvent); + EventUtils.synthesizeMouseAtCenter(gGoButton, aEvent); } else EventUtils.synthesizeKey("VK_RETURN", aEvent); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js 2014-11-26 21:45:47.000000000 +0000 @@ -41,7 +41,7 @@ gURLBar.focus(); paste(inputValue, function() { - is(gURLBar.value, expectedURL, "entering '" + inputValue + "' strips relevant bits."); + is(gURLBar.textValue, expectedURL, "entering '" + inputValue + "' strips relevant bits."); setTimeout(testNext, 0); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar.js 2014-11-26 21:45:47.000000000 +0000 @@ -0,0 +1,249 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * vim:set ts=2 sw=2 sts=2 et: + * 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/. */ + +const TEST_URL_BASES = [ + "http://example.org/browser/browser/base/content/test/general/dummy_page.html#tabmatch", + "http://example.org/browser/browser/base/content/test/general/moz.png#tabmatch" +]; + +var gController = Cc["@mozilla.org/autocomplete/controller;1"]. + getService(Ci.nsIAutoCompleteController); + +var gTabWaitCount = 0; +var gTabCounter = 0; + +var gTestSteps = [ + function() { + info("Running step 1"); + for (let i = 0; i < 10; i++) { + let tab = gBrowser.addTab(); + loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter)); + } + }, + function() { + info("Running step 2"); + gBrowser.selectTabAtIndex(1); + gBrowser.removeCurrentTab(); + gBrowser.selectTabAtIndex(1); + gBrowser.removeCurrentTab(); + for (let i = 1; i < gBrowser.tabs.length; i++) + loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter)); + }, + function() { + info("Running step 3"); + for (let i = 1; i < gBrowser.tabs.length; i++) + loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter); + }, + function() { + info("Running step 4 - ensure we don't register subframes as open pages"); + let tab = gBrowser.addTab(); + tab.linkedBrowser.addEventListener("load", function () { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + // Start the sub-document load. + executeSoon(function () { + tab.linkedBrowser.addEventListener("load", function (e) { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + ensure_opentabs_match_db(nextStep); + }, true); + tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/"; + }); + }, true); + tab.linkedBrowser.loadURI('data:text/html,'); + }, + function() { + info("Running step 5 - remove tab immediately"); + let tab = gBrowser.addTab("about:logo"); + gBrowser.removeTab(tab); + ensure_opentabs_match_db(nextStep); + }, + function() { + info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result"); + let tabToKeep = gBrowser.addTab(); + let tab = gBrowser.addTab(); + tab.linkedBrowser.addEventListener("load", function () { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab); + ensure_opentabs_match_db(function () { + gBrowser.removeTab(tabToKeep); + ensure_opentabs_match_db(nextStep); + }); + }, true); + tab.linkedBrowser.loadURI("about:mozilla"); + }, + function() { + info("Running step 7 - close all tabs"); + + Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand"); + + gBrowser.addTab("about:blank", {skipAnimation: true}); + while (gBrowser.tabs.length > 1) { + info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec); + gBrowser.selectTabAtIndex(0); + gBrowser.removeCurrentTab(); + } + ensure_opentabs_match_db(nextStep); + } +]; + + + +function test() { + waitForExplicitFinish(); + nextStep(); +} + +function loadTab(tab, url) { + // Because adding visits is async, we will not be notified immediately. + let visited = false; + let loaded = false; + + function maybeCheckResults() { + if (visited && loaded && --gTabWaitCount == 0) { + ensure_opentabs_match_db(nextStep); + } + } + + tab.linkedBrowser.addEventListener("load", function () { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + loaded = true; + maybeCheckResults(); + }, true); + + if (!visited) { + Services.obs.addObserver( + function (aSubject, aTopic, aData) { + if (url != aSubject.QueryInterface(Ci.nsIURI).spec) + return; + Services.obs.removeObserver(arguments.callee, aTopic); + visited = true; + maybeCheckResults(); + }, + "uri-visit-saved", + false + ); + } + + gTabWaitCount++; + info("Loading page: " + url); + tab.linkedBrowser.loadURI(url); +} + +function waitForRestoredTab(tab) { + gTabWaitCount++; + + tab.linkedBrowser.addEventListener("load", function () { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + if (--gTabWaitCount == 0) { + ensure_opentabs_match_db(nextStep); + } + }, true); +} + + +function nextStep() { + if (gTestSteps.length == 0) { + while (gBrowser.tabs.length > 1) { + gBrowser.selectTabAtIndex(1); + gBrowser.removeCurrentTab(); + } + + waitForClearHistory(finish); + + return; + } + + var stepFunc = gTestSteps.shift(); + stepFunc(); +} + +function ensure_opentabs_match_db(aCallback) { + var tabs = {}; + + var winEnum = Services.wm.getEnumerator("navigator:browser"); + while (winEnum.hasMoreElements()) { + let browserWin = winEnum.getNext(); + // skip closed-but-not-destroyed windows + if (browserWin.closed) + continue; + + for (let i = 0; i < browserWin.gBrowser.tabContainer.childElementCount; i++) { + let browser = browserWin.gBrowser.getBrowserAtIndex(i); + let url = browser.currentURI.spec; + if (browserWin.isBlankPageURL(url)) + continue; + if (!(url in tabs)) + tabs[url] = 1; + else + tabs[url]++; + } + } + + checkAutocompleteResults(tabs, aCallback); +} + +/** + * Clears history invoking callback when done. + */ +function waitForClearHistory(aCallback) { + const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; + let observer = { + observe: function(aSubject, aTopic, aData) { + Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED); + aCallback(); + } + }; + Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); + + PlacesUtils.bhistory.removeAllPages(); +} + +function checkAutocompleteResults(aExpected, aCallback) +{ + gController.input = { + timeout: 10, + textValue: "", + searches: ["history"], + searchParam: "enable-actions", + popupOpen: false, + minResultsForPopup: 0, + invalidate: function() {}, + disableAutoComplete: false, + completeDefaultIndex: false, + get popup() { return this; }, + onSearchBegin: function() {}, + onSearchComplete: function () + { + info("Found " + gController.matchCount + " matches."); + // Check to see the expected uris and titles match up (in any order) + for (let i = 0; i < gController.matchCount; i++) { + let uri = gController.getValueAt(i).replace(/^moz-action:[^,]+,/i, ""); + + info("Search for '" + uri + "' in open tabs."); + let expected = uri in aExpected; + ok(expected, uri + " was found in autocomplete, was " + (expected ? "" : "not ") + "expected"); + // Remove the found entry from expected results. + delete aExpected[uri]; + } + + // Make sure there is no reported open page that is not open. + for (let entry in aExpected) { + ok(false, "'" + entry + "' should be found in autocomplete"); + } + + executeSoon(aCallback); + }, + setSelectedIndex: function() {}, + get searchCount() { return this.searches.length; }, + getSearchAt: function(aIndex) this.searches[aIndex], + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIAutoCompleteInput, + Ci.nsIAutoCompletePopup, + ]) + }; + + info("Searching open pages."); + gController.startSearch(Services.prefs.getCharPref("browser.urlbar.restrict.openpage")); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar_perwindowpb.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar_perwindowpb.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar_perwindowpb.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_tabMatchesInAwesomebar_perwindowpb.js 2014-11-26 21:45:47.000000000 +0000 @@ -1,249 +1,122 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- - * vim:set ts=2 sw=2 sts=2 et: - * This Source Code Form is subject to the terms of the Mozilla Public +/* 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/. */ -const TEST_URL_BASES = [ - "http://example.org/browser/browser/base/content/test/general/dummy_page.html#tabmatch", - "http://example.org/browser/browser/base/content/test/general/moz.png#tabmatch" -]; - -var gController = Cc["@mozilla.org/autocomplete/controller;1"]. - getService(Ci.nsIAutoCompleteController); - -var gTabWaitCount = 0; -var gTabCounter = 0; - -var gTestSteps = [ - function() { - info("Running step 1"); - for (let i = 0; i < 10; i++) { - let tab = gBrowser.addTab(); - loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter)); - } - }, - function() { - info("Running step 2"); - gBrowser.selectTabAtIndex(1); - gBrowser.removeCurrentTab(); - gBrowser.selectTabAtIndex(1); - gBrowser.removeCurrentTab(); - for (let i = 1; i < gBrowser.tabs.length; i++) - loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter)); - }, - function() { - info("Running step 3"); - for (let i = 1; i < gBrowser.tabs.length; i++) - loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter); - }, - function() { - info("Running step 4 - ensure we don't register subframes as open pages"); - let tab = gBrowser.addTab(); - tab.linkedBrowser.addEventListener("load", function () { - tab.linkedBrowser.removeEventListener("load", arguments.callee, true); - // Start the sub-document load. - executeSoon(function () { - tab.linkedBrowser.addEventListener("load", function (e) { - tab.linkedBrowser.removeEventListener("load", arguments.callee, true); - ensure_opentabs_match_db(nextStep); - }, true); - tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/"; - }); - }, true); - tab.linkedBrowser.loadURI('data:text/html,'); - }, - function() { - info("Running step 5 - remove tab immediately"); - let tab = gBrowser.addTab("about:logo"); - gBrowser.removeTab(tab); - ensure_opentabs_match_db(nextStep); - }, - function() { - info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result"); - let tabToKeep = gBrowser.addTab(); - let tab = gBrowser.addTab(); - tab.linkedBrowser.addEventListener("load", function () { - tab.linkedBrowser.removeEventListener("load", arguments.callee, true); - gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab); - ensure_opentabs_match_db(function () { - gBrowser.removeTab(tabToKeep); - ensure_opentabs_match_db(nextStep); - }); - }, true); - tab.linkedBrowser.loadURI("about:mozilla"); - }, - function() { - info("Running step 7 - close all tabs"); - - Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand"); - - gBrowser.addTab("about:blank", {skipAnimation: true}); - while (gBrowser.tabs.length > 1) { - info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec); - gBrowser.selectTabAtIndex(0); - gBrowser.removeCurrentTab(); - } - ensure_opentabs_match_db(nextStep); - } -]; - - - function test() { waitForExplicitFinish(); - nextStep(); -} - -function loadTab(tab, url) { - // Because adding visits is async, we will not be notified immediately. - let visited = false; - let loaded = false; - - function maybeCheckResults() { - if (visited && loaded && --gTabWaitCount == 0) { - ensure_opentabs_match_db(nextStep); - } - } - - tab.linkedBrowser.addEventListener("load", function () { - tab.linkedBrowser.removeEventListener("load", arguments.callee, true); - loaded = true; - maybeCheckResults(); - }, true); - - if (!visited) { - Services.obs.addObserver( - function (aSubject, aTopic, aData) { - if (url != aSubject.QueryInterface(Ci.nsIURI).spec) - return; - Services.obs.removeObserver(arguments.callee, aTopic); - visited = true; - maybeCheckResults(); - }, - "uri-visit-saved", - false - ); - } - - gTabWaitCount++; - info("Loading page: " + url); - tab.linkedBrowser.loadURI(url); -} - -function waitForRestoredTab(tab) { - gTabWaitCount++; - - tab.linkedBrowser.addEventListener("load", function () { - tab.linkedBrowser.removeEventListener("load", arguments.callee, true); - if (--gTabWaitCount == 0) { - ensure_opentabs_match_db(nextStep); - } - }, true); -} - - -function nextStep() { - if (gTestSteps.length == 0) { - while (gBrowser.tabs.length > 1) { - gBrowser.selectTabAtIndex(1); - gBrowser.removeCurrentTab(); - } - waitForClearHistory(finish); - - return; - } + let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html"; - var stepFunc = gTestSteps.shift(); - stepFunc(); -} - -function ensure_opentabs_match_db(aCallback) { - var tabs = {}; - - var winEnum = Services.wm.getEnumerator("navigator:browser"); - while (winEnum.hasMoreElements()) { - let browserWin = winEnum.getNext(); - // skip closed-but-not-destroyed windows - if (browserWin.closed) - continue; - - for (let i = 0; i < browserWin.gBrowser.tabContainer.childElementCount; i++) { - let browser = browserWin.gBrowser.getBrowserAtIndex(i); - let url = browser.currentURI.spec; - if (browserWin.isBlankPageURL(url)) - continue; - if (!(url in tabs)) - tabs[url] = 1; - else - tabs[url]++; - } - } - - checkAutocompleteResults(tabs, aCallback); -} - -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let observer = { - observe: function(aSubject, aTopic, aData) { - Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } + function testOnWindow(aOptions, aCallback) { + whenNewWindowLoaded(aOptions, function(aWin) { + // execute should only be called when need, like when you are opening + // web pages on the test. If calling executeSoon() is not necesary, then + // call whenNewWindowLoaded() instead of testOnWindow() on your test. + executeSoon(function() aCallback(aWin)); + }); }; - Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - PlacesUtils.bhistory.removeAllPages(); -} + testOnWindow({}, function(aNormalWindow) { + testOnWindow({private: true}, function(aPrivateWindow) { + runTest(aNormalWindow, aPrivateWindow, false, function() { + aNormalWindow.close(); + aPrivateWindow.close(); + testOnWindow({}, function(aNormalWindow) { + testOnWindow({private: true}, function(aPrivateWindow) { + runTest(aPrivateWindow, aNormalWindow, false, function() { + aNormalWindow.close(); + aPrivateWindow.close(); + testOnWindow({private: true}, function(aPrivateWindow) { + runTest(aPrivateWindow, aPrivateWindow, false, function() { + aPrivateWindow.close(); + testOnWindow({}, function(aNormalWindow) { + runTest(aNormalWindow, aNormalWindow, true, function() { + aNormalWindow.close(); + finish(); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); -function checkAutocompleteResults(aExpected, aCallback) -{ - gController.input = { - timeout: 10, - textValue: "", - searches: ["history"], - searchParam: "enable-actions", - popupOpen: false, - minResultsForPopup: 0, - invalidate: function() {}, - disableAutoComplete: false, - completeDefaultIndex: false, - get popup() { return this; }, - onSearchBegin: function() {}, - onSearchComplete: function () - { - info("Found " + gController.matchCount + " matches."); - // Check to see the expected uris and titles match up (in any order) - for (let i = 0; i < gController.matchCount; i++) { - let uri = gController.getValueAt(i).replace(/^moz-action:[^,]+,/i, ""); - - info("Search for '" + uri + "' in open tabs."); - let expected = uri in aExpected; - ok(expected, uri + " was found in autocomplete, was " + (expected ? "" : "not ") + "expected"); - // Remove the found entry from expected results. - delete aExpected[uri]; - } - - // Make sure there is no reported open page that is not open. - for (let entry in aExpected) { - ok(false, "'" + entry + "' should be found in autocomplete"); - } - - executeSoon(aCallback); - }, - setSelectedIndex: function() {}, - get searchCount() { return this.searches.length; }, - getSearchAt: function(aIndex) this.searches[aIndex], - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIAutoCompleteInput, - Ci.nsIAutoCompletePopup, - ]) - }; + function runTest(aSourceWindow, aDestWindow, aExpectSwitch, aCallback) { + // Open the base tab + let baseTab = aSourceWindow.gBrowser.addTab(testURL); + baseTab.linkedBrowser.addEventListener("load", function() { + // Wait for the tab to be fully loaded so matching happens correctly + if (baseTab.linkedBrowser.currentURI.spec == "about:blank") + return; + baseTab.linkedBrowser.removeEventListener("load", arguments.callee, true); + + let testTab = aDestWindow.gBrowser.addTab(); + + waitForFocus(function() { + // Select the testTab + aDestWindow.gBrowser.selectedTab = testTab; + + // Ensure that this tab has no history entries + ok(testTab.linkedBrowser.sessionHistory.count < 2, + "The test tab has 1 or less history entries"); + // Ensure that this tab is on about:blank + is(testTab.linkedBrowser.currentURI.spec, "about:blank", + "The test tab is on about:blank"); + // Ensure that this tab's document has no child nodes + ok(!testTab.linkedBrowser.contentDocument.body.hasChildNodes(), + "The test tab has no child nodes"); + ok(!testTab.hasAttribute("busy"), + "The test tab doesn't have the busy attribute"); + + let urlbar = aDestWindow.gURLBar; + let controller = urlbar.controller; + + // Focus URL bar, enter value, and start searching. + urlbar.focus(); + urlbar.value = testURL; + controller.startSearch(testURL); + + // Wait for the Awesomebar popup to appear. + promisePopupShown(aDestWindow.gURLBar.popup).then(() => { + function searchIsComplete() { + return controller.searchStatus == + Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH; + } + + // Wait until the search is complete. + waitForCondition(searchIsComplete, function () { + if (aExpectSwitch) { + // If we expect a tab switch then the current tab + // will be closed and we switch to the other tab. + let tabContainer = aDestWindow.gBrowser.tabContainer; + tabContainer.addEventListener("TabClose", function onClose(event) { + if (event.target == testTab) { + tabContainer.removeEventListener("TabClose", onClose); + executeSoon(aCallback); + } + }); + } else { + // If we don't expect a tab switch then wait for the tab to load. + testTab.addEventListener("load", function onLoad() { + testTab.removeEventListener("load", onLoad, true); + executeSoon(aCallback); + }, true); + } + + // Select the second match, if any. + if (controller.matchCount > 1) { + controller.handleKeyNavigation(KeyEvent.DOM_VK_DOWN); + } + + // Execute the selected action. + controller.handleEnter(true); + }); + }); - info("Searching open pages."); - gController.startSearch(Services.prefs.getCharPref("browser.urlbar.restrict.openpage")); + }, aDestWindow); + }, true); + } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js 2014-11-26 21:45:47.000000000 +0000 @@ -27,7 +27,7 @@ }; let history = Cc["@mozilla.org/browser/history;1"] .getService(Ci.mozIAsyncHistory); - history.updatePlaces({ uri: NetUtil.newURI("http://www.autofilltrimurl.com/") + history.updatePlaces({ uri: NetUtil.newURI("http://www.autofilltrimurl.com/whatever") , visits: [ { transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED , visitDate: Date.now() * 1000 } ] @@ -44,7 +44,8 @@ EventUtils.synthesizeKey(aTyped.substr(-1), {}); waitForSearchComplete(function () { - is(gURLBar.value, aExpected, "trim was applied correctly"); + info(`Got value: ${gURLBar.value}`); + is(gURLBar.value, aExpected, "Autofilled value is as expected"); aCallback(); }); } @@ -53,9 +54,9 @@ test_autoFill("http://au", "http://autofilltrimurl.com/", function () { test_autoFill("http://www.autofilltrimurl.com", "http://www.autofilltrimurl.com/", function () { // Now ensure selecting from the popup correctly trims. - is(gURLBar.controller.matchCount, 1, "Found the expected number of matches"); + is(gURLBar.controller.matchCount, 2, "Found the expected number of matches"); EventUtils.synthesizeKey("VK_DOWN", {}); - is(gURLBar.value, "www.autofilltrimurl.com", "trim was applied correctly"); + is(gURLBar.textValue, "www.autofilltrimurl.com/whatever", "trim was applied correctly"); gURLBar.closePopup(); waitForClearHistory(finish); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarCopying.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarCopying.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarCopying.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarCopying.js 2014-11-26 21:45:47.000000000 +0000 @@ -156,7 +156,7 @@ function doCheck() { if (test.setURL || test.loadURL) { gURLBar.valueIsTyped = !!test.setURL; - is(gURLBar.value, test.expectedURL, "url bar value set"); + is(gURLBar.textValue, test.expectedURL, "url bar value set"); } testCopy(test.copyVal, test.copyExpected, cb); @@ -180,7 +180,7 @@ let endBracket = copyVal.indexOf(">"); if (startBracket == -1 || endBracket == -1 || startBracket > endBracket || - copyVal.replace("<", "").replace(">", "") != gURLBar.value) { + copyVal.replace("<", "").replace(">", "") != gURLBar.textValue) { ok(false, "invalid copyVal: " + copyVal); } gURLBar.selectionStart = startBracket; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarEnter.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarEnter.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarEnter.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarEnter.js 2014-11-26 21:45:47.000000000 +0000 @@ -51,12 +51,12 @@ ] function checkCurrent(aTab) { - is(gURLBar.value, TEST_VALUE, "Urlbar should preserve the value on return keypress"); + is(gURLBar.textValue, TEST_VALUE, "Urlbar should preserve the value on return keypress"); is(gBrowser.selectedTab, aTab, "New URL was loaded in the current tab"); } function checkNewTab(aTab) { - is(gURLBar.value, TEST_VALUE, "Urlbar should preserve the value on return keypress"); + is(gURLBar.textValue, TEST_VALUE, "Urlbar should preserve the value on return keypress"); isnot(gBrowser.selectedTab, aTab, "New URL was loaded in a new tab"); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_URLBarSetURI.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_URLBarSetURI.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_URLBarSetURI.js 2014-11-14 09:37:11.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_URLBarSetURI.js 2014-11-26 21:45:47.000000000 +0000 @@ -31,7 +31,7 @@ function revert(next) { loadTabInWindow(window, function (tab) { gURLBar.handleRevert(); - is(gURLBar.value, "example.com", "URL bar had user/pass stripped after reverting"); + is(gURLBar.textValue, "example.com", "URL bar had user/pass stripped after reverting"); gBrowser.removeTab(tab); next(); }); @@ -44,7 +44,7 @@ loadTabInWindow(win, function () { openToolbarCustomizationUI(function () { closeToolbarCustomizationUI(function () { - is(win.gURLBar.value, "example.com", "URL bar had user/pass stripped after customize"); + is(win.gURLBar.textValue, "example.com", "URL bar had user/pass stripped after customize"); win.close(); next(); }, win); @@ -59,7 +59,7 @@ // error. tab.linkedBrowser.loadURI("http://test1.example.com"); tab.linkedBrowser.stop(); - is(gURLBar.value, "example.com", "URL bar had user/pass stripped after load error"); + is(gURLBar.textValue, "example.com", "URL bar had user/pass stripped after load error"); gBrowser.removeTab(tab); next(); }); @@ -76,7 +76,7 @@ return; tab.linkedBrowser.removeEventListener("load", listener, true); - is(win.gURLBar.value, "example.com", "URL bar had user/pass stripped initially"); + is(win.gURLBar.textValue, "example.com", "URL bar had user/pass stripped initially"); callback(tab); }, true); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarStop.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarStop.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarStop.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarStop.js 2014-11-26 21:45:47.000000000 +0000 @@ -11,23 +11,23 @@ function onload() { gBrowser.selectedBrowser.removeEventListener("load", onload, true); - is(gURLBar.value, gURLBar.trimValue(goodURL), "location bar reflects loaded page"); + is(gURLBar.textValue, gURLBar.trimValue(goodURL), "location bar reflects loaded page"); typeAndSubmit(badURL); - is(gURLBar.value, gURLBar.trimValue(badURL), "location bar reflects loading page"); + is(gURLBar.textValue, gURLBar.trimValue(badURL), "location bar reflects loading page"); gBrowser.contentWindow.stop(); - is(gURLBar.value, gURLBar.trimValue(goodURL), "location bar reflects loaded page after stop()"); + is(gURLBar.textValue, gURLBar.trimValue(goodURL), "location bar reflects loaded page after stop()"); gBrowser.removeCurrentTab(); gBrowser.selectedTab = gBrowser.addTab("about:blank"); - is(gURLBar.value, "", "location bar is empty"); + is(gURLBar.textValue, "", "location bar is empty"); typeAndSubmit(badURL); - is(gURLBar.value, gURLBar.trimValue(badURL), "location bar reflects loading page"); + is(gURLBar.textValue, gURLBar.trimValue(badURL), "location bar reflects loading page"); gBrowser.contentWindow.stop(); - is(gURLBar.value, gURLBar.trimValue(badURL), "location bar reflects stopped page in an empty tab"); + is(gURLBar.textValue, gURLBar.trimValue(badURL), "location bar reflects stopped page in an empty tab"); gBrowser.removeCurrentTab(); finish(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarTrimURLs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarTrimURLs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/browser_urlbarTrimURLs.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/browser_urlbarTrimURLs.js 2014-11-26 21:45:47.000000000 +0000 @@ -5,7 +5,7 @@ function testVal(originalValue, targetValue) { gURLBar.value = originalValue; gURLBar.valueIsTyped = false; - is(gURLBar.value, targetValue || originalValue, "url bar value set"); + is(gURLBar.textValue, targetValue || originalValue, "url bar value set"); } function test() { @@ -96,7 +96,7 @@ function testCopy(originalValue, targetValue, cb) { waitForClipboard(targetValue, function () { - is(gURLBar.value, originalValue, "url bar copy value set"); + is(gURLBar.textValue, originalValue, "url bar copy value set"); gURLBar.focus(); gURLBar.select(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/head.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/head.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/general/head.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/general/head.js 2014-11-26 21:45:47.000000000 +0000 @@ -6,6 +6,8 @@ "resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils", + "resource://testing-common/PlacesTestUtils.jsm"); function closeAllNotifications () { let notificationBox = document.getElementById("global-notificationbox"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/newtab/browser.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/newtab/browser.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/newtab/browser.ini 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/newtab/browser.ini 2014-11-26 21:45:47.000000000 +0000 @@ -21,6 +21,7 @@ [browser_newtab_bug998387.js] [browser_newtab_disable.js] [browser_newtab_drag_drop.js] +skip-if = os == "win" && debug # bug 1097056; test fails in --run-by-dir mode on win8 x64 debug [browser_newtab_drag_drop_ext.js] [browser_newtab_drop_preview.js] [browser_newtab_enhanced.js] @@ -44,3 +45,4 @@ [browser_newtab_undo.js] [browser_newtab_unpin.js] [browser_newtab_update.js] +skip-if = true # Bug 1008029 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js 2014-11-26 21:45:47.000000000 +0000 @@ -4,11 +4,13 @@ let gTestBrowser = null; -let propBagProperties = { +let crashedEventProperties = { pluginName: "GlobalTestPlugin", pluginDumpID: "1234", browserDumpID: "5678", - submittedCrashReport: false + submittedCrashReport: false, + bubbles: true, + cancelable: true } // Test that plugin crash submissions still work properly after @@ -34,15 +36,9 @@ function generateCrashEvent() { let window = gTestBrowser.contentWindow; - let propBag = Cc["@mozilla.org/hash-property-bag;1"] - .createInstance(Ci.nsIWritablePropertyBag); - for (let [name, val] of Iterator(propBagProperties)) { - propBag.setProperty(name, val); - } + let crashedEvent = new window.PluginCrashedEvent("PluginCrashed", crashedEventProperties); - let event = window.document.createEvent("CustomEvent"); - event.initCustomEvent("PluginCrashed", true, true, propBag); - window.dispatchEvent(event); + window.dispatchEvent(crashedEvent); } @@ -50,13 +46,10 @@ let target = event.target; is (target, gTestBrowser.contentWindow, "Event target is the window."); - let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2); - for (let [name, val] of Iterator(propBagProperties)) { - let type = typeof val; - let propVal = type == "string" - ? propBag.getPropertyAsAString(name) - : propBag.getPropertyAsBool(name); - is (propVal, val, "Correct property in detail propBag: " + name + "."); + for (let [name, val] of Iterator(crashedEventProperties)) { + let propVal = event[name]; + + is (propVal, val, "Correct property: " + name + "."); } waitForNotificationBar("plugin-crashed", gTestBrowser, (notification) => { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js 2014-11-26 21:45:47.000000000 +0000 @@ -57,10 +57,8 @@ } if (message.data.sendCrashMessage) { - let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2); - let crashID = propBag.getPropertyAsAString("pluginDumpID"); sendAsyncMessage("test:crash-plugin:crashed", { - crashID: crashID, + crashID: event.pluginDumpID, }); return; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/urlbarBindings.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/urlbarBindings.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/base/content/urlbarBindings.xml 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/base/content/urlbarBindings.xml 2014-11-26 21:45:47.000000000 +0000 @@ -132,9 +132,7 @@ --> @@ -285,31 +283,31 @@ var mayInheritPrincipal = false; var postData = null; - var action = this._parseActionUrl(url); + let action = this._parseActionUrl(this._value); let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; let matchLastLocationChange = true; if (action) { - if (this.hasAttribute("actiontype")) { - if (action.type == "switchtab") { - url = action.params.url; + if (action.type == "switchtab") { + url = action.params.url; + if (this.hasAttribute("actiontype")) { this.handleRevert(); let prevTab = gBrowser.selectedTab; if (switchToTabHavingURI(url) && isTabEmpty(prevTab)) gBrowser.removeTab(prevTab); return; - } else if (action.type == "keyword") { - url = action.params.url; - } else if (action.type == "searchengine") { - let engine = Services.search.getEngineByName(action.params.engineName); - let submission = engine.getSubmission(action.params.searchQuery); - - url = submission.uri.spec; - postData = submission.postData; - } else if (action.type == "visiturl") { - url = action.params.url; } + } else if (action.type == "keyword") { + url = action.params.url; + } else if (action.type == "searchengine") { + let engine = Services.search.getEngineByName(action.params.engineName); + let submission = engine.getSubmission(action.params.searchQuery); + + url = submission.uri.spec; + postData = submission.postData; + } else if (action.type == "visiturl") { + url = action.params.url; } continueOperation.call(this); } @@ -584,7 +582,11 @@ urlbar.inputField.value = urlbar.inputField.value.substring(0, start) + urlbar.inputField.value.substring(end); urlbar.selectionStart = urlbar.selectionEnd = start; - urlbar.removeAttribute("actiontype"); + + let event = document.createEvent("UIEvents"); + event.initUIEvent("input", true, false, window, 0); + urlbar.dispatchEvent(event); + SetPageProxyState("invalid"); } @@ -704,8 +706,10 @@ ]]> - + + + + + + + @@ -819,7 +837,7 @@ + + + + + + + 0 ? 0 : maxRow; + } else if (newIndex > maxRow) { + newIndex = index < maxRow ? maxRow : 0; + } + + return newIndex; + ]]> + + + + + + 0 && this.selectedIndex == -1) + this.selectedIndex = 0; + ]]> + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/customizableui/content/customizeMode.inc.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/customizableui/content/customizeMode.inc.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/customizableui/content/customizeMode.inc.xul 2014-11-14 09:37:12.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/customizableui/content/customizeMode.inc.xul 2014-11-26 21:45:48.000000000 +0000 @@ -56,8 +56,8 @@ + ); + } + return ( +
+ {backButton} +

{this.props.title}

+ {this.props.children} +
+ ); + } + }); + + /** + * Detailed feedback form. + */ + var FeedbackForm = React.createClass({ + propTypes: { + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), + pending: React.PropTypes.bool, + reset: React.PropTypes.func + }, + + getInitialState: function() { + return {category: "", description: ""}; + }, + + getDefaultProps: function() { + return {pending: false}; + }, + + _getCategories: function() { + return { + audio_quality: l10n.get("feedback_category_audio_quality"), + video_quality: l10n.get("feedback_category_video_quality"), + disconnected : l10n.get("feedback_category_was_disconnected"), + confusing: l10n.get("feedback_category_confusing"), + other: l10n.get("feedback_category_other") + }; + }, + + _getCategoryFields: function() { + var categories = this._getCategories(); + return Object.keys(categories).map(function(category, key) { + return ( + + ); + }, this); + }, + + /** + * Checks if the form is ready for submission: + * + * - no feedback submission should be pending. + * - a category (reason) must be chosen; + * - if the "other" category is chosen, a custom description must have been + * entered by the end user; + * + * @return {Boolean} + */ + _isFormReady: function() { + if (this.props.pending || !this.state.category) { + return false; + } + if (this.state.category === "other" && !this.state.description) { + return false; + } + return true; + }, + + handleCategoryChange: function(event) { + var category = event.target.value; + this.setState({ + category: category, + description: category == "other" ? "" : this._getCategories()[category] + }); + if (category == "other") { + this.refs.description.getDOMNode().focus(); + } + }, + + handleDescriptionFieldChange: function(event) { + this.setState({description: event.target.value}); + }, + + handleDescriptionFieldFocus: function(event) { + this.setState({category: "other", description: ""}); + }, + + handleFormSubmit: function(event) { + event.preventDefault(); + // XXX this feels ugly, we really want a feedbackActions object here. + this.props.feedbackStore.dispatchAction(new sharedActions.SendFeedback({ + happy: false, + category: this.state.category, + description: this.state.description + })); + }, + + render: function() { + var descriptionDisplayValue = this.state.category === "other" ? + this.state.description : ""; + return ( + +
+ {this._getCategoryFields()} +

+ +

+ +
+
+ ); + } + }); + + /** + * Feedback received view. + * + * Props: + * - {Function} onAfterFeedbackReceived Function to execute after the + * WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS timeout has elapsed + */ + var FeedbackReceived = React.createClass({ + propTypes: { + onAfterFeedbackReceived: React.PropTypes.func + }, + + getInitialState: function() { + return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS}; + }, + + componentDidMount: function() { + this._timer = setInterval(function() { + this.setState({countdown: this.state.countdown - 1}); + }.bind(this), 1000); + }, + + componentWillUnmount: function() { + if (this._timer) { + clearInterval(this._timer); + } + }, + + render: function() { + if (this.state.countdown < 1) { + clearInterval(this._timer); + if (this.props.onAfterFeedbackReceived) { + this.props.onAfterFeedbackReceived(); + } + } + return ( + +

{ + l10n.get("feedback_window_will_close_in2", { + countdown: this.state.countdown, + num: this.state.countdown + })}

+
+ ); + } + }); + + /** + * Feedback view. + */ + var FeedbackView = React.createClass({ + mixins: [Backbone.Events], + + propTypes: { + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), + onAfterFeedbackReceived: React.PropTypes.func, + // Used by the UI showcase. + feedbackState: React.PropTypes.string + }, + + getInitialState: function() { + var storeState = this.props.feedbackStore.getStoreState(); + return _.extend({}, storeState, { + feedbackState: this.props.feedbackState || storeState.feedbackState + }); + }, + + componentWillMount: function() { + this.listenTo(this.props.feedbackStore, "change", this._onStoreStateChanged); + }, + + componentWillUnmount: function() { + this.stopListening(this.props.feedbackStore); + }, + + _onStoreStateChanged: function() { + this.setState(this.props.feedbackStore.getStoreState()); + }, + + reset: function() { + this.setState(this.props.feedbackStore.getInitialStoreState()); + }, + + handleHappyClick: function() { + // XXX: If the user is happy, we directly send this information to the + // feedback API; this is a behavior we might want to revisit later. + this.props.feedbackStore.dispatchAction(new sharedActions.SendFeedback({ + happy: true, + category: "", + description: "" + })); + }, + + handleSadClick: function() { + this.props.feedbackStore.dispatchAction( + new sharedActions.RequireFeedbackDetails()); + }, + + _onFeedbackSent: function(err) { + if (err) { + // XXX better end user error reporting, see bug 1046738 + console.error("Unable to send user feedback", err); + } + this.setState({pending: false, step: "finished"}); + }, + + render: function() { + switch(this.state.feedbackState) { + default: + case FEEDBACK_STATES.INIT: { + return ( + +
+ + +
+
+ ); + } + case FEEDBACK_STATES.DETAILS: { + return ( + + ); + } + case FEEDBACK_STATES.PENDING: + case FEEDBACK_STATES.SENT: + case FEEDBACK_STATES.FAILED: { + if (this.state.error) { + // XXX better end user error reporting, see bug 1046738 + console.error("Error encountered while submitting feedback", + this.state.error); + } + return ( + + ); + } + } + } + }); + + return FeedbackView; +})(navigator.mozL10n || document.mozL10n); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/mixins.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/mixins.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/mixins.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/mixins.js 2014-11-26 21:45:48.000000000 +0000 @@ -154,6 +154,10 @@ * @param {String} name The filename to play (excluding the extension). */ play: function(name, options) { + if (this._isLoopDesktop() && rootObject.navigator.mozLoop.doNotDisturb) { + return; + } + options = options || {}; options.loop = options.loop || false; @@ -222,8 +226,66 @@ } }; + /** + * A mixin especially for rooms. This plays the right sound according to + * the state changes. Requires AudioMixin to also be used. + */ + var RoomsAudioMixin = { + mixins: [AudioMixin], + + componentWillUpdate: function(nextProps, nextState) { + var ROOM_STATES = loop.store.ROOM_STATES; + + function isConnectedToRoom(state) { + return state === ROOM_STATES.HAS_PARTICIPANTS || + state === ROOM_STATES.SESSION_CONNECTED; + } + + function notConnectedToRoom(state) { + // Failed and full are states that the user is not + // really connected to the room, but we don't want to + // catch those here, as they get their own sounds. + return state === ROOM_STATES.INIT || + state === ROOM_STATES.GATHER || + state === ROOM_STATES.READY || + state === ROOM_STATES.JOINED || + state === ROOM_STATES.ENDED; + } + + // Joining the room. + if (notConnectedToRoom(this.state.roomState) && + isConnectedToRoom(nextState.roomState)) { + this.play("room-joined"); + } + + // Other people coming and leaving. + if (this.state.roomState === ROOM_STATES.SESSION_CONNECTED && + nextState.roomState === ROOM_STATES.HAS_PARTICIPANTS) { + this.play("room-joined-in"); + } + + if (this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS && + nextState.roomState === ROOM_STATES.SESSION_CONNECTED) { + this.play("room-left"); + } + + // Leaving the room - same sound as if a participant leaves + if (isConnectedToRoom(this.state.roomState) && + notConnectedToRoom(nextState.roomState)) { + this.play("room-left"); + } + + // Room failures + if (nextState.roomState === ROOM_STATES.FAILED || + nextState.roomState === ROOM_STATES.FULL) { + this.play("failure"); + } + } + }; + return { AudioMixin: AudioMixin, + RoomsAudioMixin: RoomsAudioMixin, setRootObject: setRootObject, DropdownMenuMixin: DropdownMenuMixin, DocumentVisibilityMixin: DocumentVisibilityMixin, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/models.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/models.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/models.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/models.js 2014-11-26 21:45:48.000000000 +0000 @@ -95,6 +95,13 @@ if (selectedCallType) { this.set("selectedCallType", selectedCallType); } + this.trigger("call:outgoing:get-media-privs"); + }, + + /** + * Used to indicate that media privileges have been accepted. + */ + gotMediaPrivs: function() { this.trigger("call:outgoing:setup"); }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/otSdkDriver.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/otSdkDriver.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/otSdkDriver.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/otSdkDriver.js 2014-11-26 21:45:48.000000000 +0000 @@ -8,6 +8,7 @@ loop.OTSdkDriver = (function() { var sharedActions = loop.shared.actions; + var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS; /** * This is a wrapper for the OT sdk. It is used to translate the SDK events into @@ -47,8 +48,11 @@ // the initial connect of the session. This saves time when setting up // the media. this.publisher = this.sdk.initPublisher(this.getLocalElement(), - this.publisherConfig, - this._onPublishComplete.bind(this)); + this.publisherConfig); + this.publisher.on("accessAllowed", this._onPublishComplete.bind(this)); + this.publisher.on("accessDenied", this._onPublishDenied.bind(this)); + this.publisher.on("accessDialogOpened", + this._onAccessDialogOpened.bind(this)); }, /** @@ -96,16 +100,12 @@ */ disconnectSession: function() { if (this.session) { - this.session.off("streamCreated", this._onRemoteStreamCreated.bind(this)); - this.session.off("connectionDestroyed", - this._onConnectionDestroyed.bind(this)); - this.session.off("sessionDisconnected", - this._onSessionDisconnected.bind(this)); - + this.session.off("streamCreated connectionDestroyed sessionDisconnected"); this.session.disconnect(); delete this.session; } if (this.publisher) { + this.publisher.off("accessAllowed accessDenied accessDialogOpened"); this.publisher.destroy(); delete this.publisher; } @@ -126,7 +126,7 @@ if (error) { console.error("Failed to complete connection", error); this.dispatcher.dispatch(new sharedActions.ConnectionFailure({ - reason: "couldNotConnect" + reason: FAILURE_REASONS.COULD_NOT_CONNECT })); return; } @@ -159,7 +159,7 @@ // We only need to worry about the network disconnected reason here. if (event.reason === "networkDisconnected") { this.dispatcher.dispatch(new sharedActions.ConnectionFailure({ - reason: "networkDisconnected" + reason: FAILURE_REASONS.NETWORK_DISCONNECTED })); } }, @@ -189,24 +189,42 @@ }, /** - * Handles the publishing being complete. + * Called from the sdk when the media access dialog is opened. + * Prevents the default action, to prevent the SDK's "allow access" + * dialog from being shown. * - * @param {Error} error An OT error object, null if there was no error. + * @param {OT.Event} event */ - _onPublishComplete: function(error) { - if (error) { - console.error("Failed to initialize publisher", error); - this.dispatcher.dispatch(new sharedActions.ConnectionFailure({ - reason: "noMedia" - })); - return; - } + _onAccessDialogOpened: function(event) { + event.preventDefault(); + }, + /** + * Handles the publishing being complete. + * + * @param {OT.Event} event + */ + _onPublishComplete: function(event) { + event.preventDefault(); this._publisherReady = true; this._maybePublishLocalStream(); }, /** + * Handles publishing of media being denied. + * + * @param {OT.Event} event + */ + _onPublishDenied: function(event) { + // This prevents the SDK's "access denied" dialog showing. + event.preventDefault(); + + this.dispatcher.dispatch(new sharedActions.ConnectionFailure({ + reason: FAILURE_REASONS.MEDIA_DENIED + })); + }, + + /** * Publishes the local stream if the session is connected * and the publisher is ready. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/roomStore.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/roomStore.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/roomStore.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/roomStore.js 2014-11-26 21:45:48.000000000 +0000 @@ -47,51 +47,14 @@ /** * Room store. * - * Options: - * - {loop.Dispatcher} dispatcher The dispatcher for dispatching actions + * @param {loop.Dispatcher} dispatcher The dispatcher for dispatching actions * and registering to consume actions. + * @param {Object} options Options object: * - {mozLoop} mozLoop The MozLoop API object. * - {ActiveRoomStore} activeRoomStore An optional substore for active room * state. - * - * @extends {Backbone.Events} - * @param {Object} options Options object. */ - function RoomStore(options) { - options = options || {}; - - if (!options.dispatcher) { - throw new Error("Missing option dispatcher"); - } - this._dispatcher = options.dispatcher; - - if (!options.mozLoop) { - throw new Error("Missing option mozLoop"); - } - this._mozLoop = options.mozLoop; - - if (options.activeRoomStore) { - this.activeRoomStore = options.activeRoomStore; - this.setStoreState({activeRoom: this.activeRoomStore.getStoreState()}); - this.activeRoomStore.on("change", - this._onActiveRoomStoreChange.bind(this)); - } - - this._dispatcher.register(this, [ - "createRoom", - "createRoomError", - "copyRoomUrl", - "deleteRoom", - "deleteRoomError", - "emailRoomUrl", - "getAllRooms", - "getAllRoomsError", - "openRoom", - "updateRoomList" - ]); - } - - RoomStore.prototype = _.extend({ + loop.store.RoomStore = loop.store.createStore({ /** * Maximum size given to createRoom; only 2 is supported (and is * always passed) because that's what the user-experience is currently @@ -107,58 +70,44 @@ defaultExpiresIn: 24 * 7 * 8, /** - * Internal store state representation. - * @type {Object} - * @see #getStoreState + * Registered actions. + * @type {Array} */ - _storeState: { - activeRoom: {}, - error: null, - pendingCreation: false, - pendingInitialRetrieval: false, - rooms: [] - }, + actions: [ + "createRoom", + "createRoomError", + "copyRoomUrl", + "deleteRoom", + "deleteRoomError", + "emailRoomUrl", + "getAllRooms", + "getAllRoomsError", + "openRoom", + "renameRoom", + "updateRoomList" + ], - /** - * Retrieves current store state. The returned state object holds the - * following properties: - * - * - {Boolean} pendingCreation Pending room creation flag. - * - {Boolean} pendingInitialRetrieval Pending initial list retrieval flag. - * - {Array} rooms The current room list. - * - {Error} error Latest error encountered, if any. - * - {Object} activeRoom Active room data, if any. - * - * You can request a given state property by providing the `key` argument. - * - * @param {String|undefined} key An optional state property name. - * @return {Object} - */ - getStoreState: function(key) { - if (key) { - return this._storeState[key]; + initialize: function(options) { + if (!options.mozLoop) { + throw new Error("Missing option mozLoop"); } - return this._storeState; - }, + this._mozLoop = options.mozLoop; - /** - * Updates store state and trigger a global "change" event, plus one for - * each provided newState property: - * - * - change:rooms - * - change:pendingInitialRetrieval - * - change:pendingCreation - * - change:error - * - change:activeRoom - * - * @param {Object} newState The new store state object. - */ - setStoreState: function(newState) { - for (var key in newState) { - this._storeState[key] = newState[key]; - this.trigger("change:" + key); + if (options.activeRoomStore) { + this.activeRoomStore = options.activeRoomStore; + this.activeRoomStore.on("change", + this._onActiveRoomStoreChange.bind(this)); } - this.trigger("change"); + }, + + getInitialStoreState: function() { + return { + activeRoom: this.activeRoomStore ? this.activeRoomStore.getStoreState() : {}, + error: null, + pendingCreation: false, + pendingInitialRetrieval: false, + rooms: [] + }; }, /** @@ -179,15 +128,6 @@ }, /** - * Local proxy helper to dispatch an action. - * - * @param {Action} action The action to dispatch. - */ - _dispatchAction: function(action) { - this._dispatcher.dispatch(action); - }, - - /** * Updates current room list when a new room is available. * * @param {String} eventName The event name (unused). @@ -196,7 +136,7 @@ _onRoomAdded: function(eventName, addedRoomData) { addedRoomData.participants = []; addedRoomData.ctime = new Date().getTime(); - this._dispatchAction(new sharedActions.UpdateRoomList({ + this.dispatchAction(new sharedActions.UpdateRoomList({ roomList: this._storeState.rooms.concat(new Room(addedRoomData)) })); }, @@ -208,7 +148,7 @@ * @param {Object} updatedRoomData The updated room data. */ _onRoomUpdated: function(eventName, updatedRoomData) { - this._dispatchAction(new sharedActions.UpdateRoomList({ + this.dispatchAction(new sharedActions.UpdateRoomList({ roomList: this._storeState.rooms.map(function(room) { return room.roomToken === updatedRoomData.roomToken ? updatedRoomData : room; @@ -223,7 +163,7 @@ * @param {Object} removedRoomData The removed room data. */ _onRoomRemoved: function(eventName, removedRoomData) { - this._dispatchAction(new sharedActions.UpdateRoomList({ + this.dispatchAction(new sharedActions.UpdateRoomList({ roomList: this._storeState.rooms.filter(function(room) { return room.roomToken !== removedRoomData.roomToken; }) @@ -302,7 +242,7 @@ this._mozLoop.rooms.create(roomCreationData, function(err) { this.setStoreState({pendingCreation: false}); if (err) { - this._dispatchAction(new sharedActions.CreateRoomError({error: err})); + this.dispatchAction(new sharedActions.CreateRoomError({error: err})); } }.bind(this)); }, @@ -345,7 +285,7 @@ deleteRoom: function(actionData) { this._mozLoop.rooms.delete(actionData.roomToken, function(err) { if (err) { - this._dispatchAction(new sharedActions.DeleteRoomError({error: err})); + this.dispatchAction(new sharedActions.DeleteRoomError({error: err})); } }.bind(this)); }, @@ -375,7 +315,7 @@ action = new sharedActions.UpdateRoomList({roomList: rawRoomList}); } - this._dispatchAction(action); + this.dispatchAction(action); // We can only start listening to room events after getAll() has been // called executed first. @@ -411,8 +351,21 @@ */ openRoom: function(actionData) { this._mozLoop.rooms.open(actionData.roomToken); - } - }, Backbone.Events); + }, - loop.store.RoomStore = RoomStore; + /** + * Renames a room. + * + * @param {sharedActions.RenameRoom} actionData + */ + renameRoom: function(actionData) { + this._mozLoop.rooms.rename(actionData.roomToken, actionData.newRoomName, + function(err) { + if (err) { + // XXX Give this a proper UI - bug 1100595. + console.error("Failed to rename the room", err); + } + }); + } + }); })(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/store.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/store.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/store.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/store.js 2014-11-26 21:45:48.000000000 +0000 @@ -0,0 +1,96 @@ +/* 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/. */ + +/* global loop:true */ + +var loop = loop || {}; +loop.store = loop.store || {}; + +loop.store.createStore = (function() { + "use strict"; + + var baseStorePrototype = { + __registerActions: function(actions) { + // check that store methods are implemented + actions.forEach(function(handler) { + if (typeof this[handler] !== "function") { + throw new Error("Store should implement an action handler for " + + handler); + } + }, this); + this.dispatcher.register(this, actions); + }, + + /** + * Proxy helper for dispatching an action from this store. + * + * @param {sharedAction.Action} action The action to dispatch. + */ + dispatchAction: function(action) { + this.dispatcher.dispatch(action); + }, + + /** + * Returns current store state. You can request a given state property by + * providing the `key` argument. + * + * @param {String|undefined} key An optional state property name. + * @return {Mixed} + */ + getStoreState: function(key) { + return key ? this._storeState[key] : this._storeState; + }, + + /** + * Updates store state and trigger a global "change" event, plus one for + * each provided newState property. + * + * @param {Object} newState The new store state object. + */ + setStoreState: function(newState) { + for (var key in newState) { + this._storeState[key] = newState[key]; + this.trigger("change:" + key); + } + this.trigger("change"); + } + }; + + /** + * Creates a new Store constructor. + * + * @param {Object} storeProto The store prototype. + * @return {Function} A store constructor. + */ + function createStore(storeProto) { + var BaseStore = function(dispatcher, options) { + options = options || {}; + + if (!dispatcher) { + throw new Error("Missing required dispatcher"); + } + this.dispatcher = dispatcher; + if (Array.isArray(this.actions)) { + this.__registerActions(this.actions); + } + + if (typeof this.initialize === "function") { + this.initialize(options); + } + + if (typeof this.getInitialStoreState === "function") { + this._storeState = this.getInitialStoreState(); + } else { + this._storeState = {}; + } + }; + BaseStore.prototype = _.extend({}, // destination object + Backbone.Events, + baseStorePrototype, + storeProto); + return BaseStore; + } + + return createStore; +})(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/utils.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/utils.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/utils.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/utils.js 2014-11-26 21:45:48.000000000 +0000 @@ -17,6 +17,14 @@ AUDIO_ONLY: "audio" }; + var FAILURE_REASONS = { + MEDIA_DENIED: "reason-media-denied", + COULD_NOT_CONNECT: "reason-could-not-connect", + NETWORK_DISCONNECTED: "reason-network-disconnected", + EXPIRED_OR_INVALID: "reason-expired-or-invalid", + UNKNOWN: "reason-unknown" + }; + /** * Format a given date into an l10n-friendly string. * @@ -40,7 +48,7 @@ */ function getBoolPreference(prefName) { if (navigator.mozLoop) { - return !!navigator.mozLoop.getLoopBoolPref(prefName); + return !!navigator.mozLoop.getLoopPref(prefName); } return !!localStorage.getItem(prefName); @@ -102,7 +110,7 @@ mozL10n.get("share_email_body4", { callUrl: callUrl, clientShortname: mozL10n.get("clientShortname2"), - learnMoreUrl: navigator.mozLoop.getLoopCharPref("learnMoreUrl") + learnMoreUrl: navigator.mozLoop.getLoopPref("learnMoreUrl") }), recipient ); @@ -110,6 +118,7 @@ return { CALL_TYPES: CALL_TYPES, + FAILURE_REASONS: FAILURE_REASONS, Helper: Helper, composeCallUrlEmail: composeCallUrlEmail, formatDate: formatDate, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/views.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/views.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/views.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/views.js 2014-11-26 21:45:48.000000000 +0000 @@ -14,8 +14,6 @@ var sharedModels = loop.shared.models; var sharedMixins = loop.shared.mixins; - var WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS = 5; - /** * Media control button. * @@ -346,287 +344,6 @@ }); /** - * Feedback outer layout. - * - * Props: - * - - */ - var FeedbackLayout = React.createClass({displayName: 'FeedbackLayout', - propTypes: { - children: React.PropTypes.component.isRequired, - title: React.PropTypes.string.isRequired, - reset: React.PropTypes.func // if not specified, no Back btn is shown - }, - - render: function() { - var backButton = React.DOM.div(null); - if (this.props.reset) { - backButton = ( - React.DOM.button({className: "fx-embedded-btn-back", type: "button", - onClick: this.props.reset}, - "« ", l10n.get("feedback_back_button") - ) - ); - } - return ( - React.DOM.div({className: "feedback"}, - backButton, - React.DOM.h3(null, this.props.title), - this.props.children - ) - ); - } - }); - - /** - * Detailed feedback form. - */ - var FeedbackForm = React.createClass({displayName: 'FeedbackForm', - propTypes: { - pending: React.PropTypes.bool, - sendFeedback: React.PropTypes.func, - reset: React.PropTypes.func - }, - - getInitialState: function() { - return {category: "", description: ""}; - }, - - getDefaultProps: function() { - return {pending: false}; - }, - - _getCategories: function() { - return { - audio_quality: l10n.get("feedback_category_audio_quality"), - video_quality: l10n.get("feedback_category_video_quality"), - disconnected : l10n.get("feedback_category_was_disconnected"), - confusing: l10n.get("feedback_category_confusing"), - other: l10n.get("feedback_category_other") - }; - }, - - _getCategoryFields: function() { - var categories = this._getCategories(); - return Object.keys(categories).map(function(category, key) { - return ( - React.DOM.label({key: key, className: "feedback-category-label"}, - React.DOM.input({type: "radio", ref: "category", name: "category", - className: "feedback-category-radio", - value: category, - onChange: this.handleCategoryChange, - checked: this.state.category === category}), - categories[category] - ) - ); - }, this); - }, - - /** - * Checks if the form is ready for submission: - * - * - no feedback submission should be pending. - * - a category (reason) must be chosen; - * - if the "other" category is chosen, a custom description must have been - * entered by the end user; - * - * @return {Boolean} - */ - _isFormReady: function() { - if (this.props.pending || !this.state.category) { - return false; - } - if (this.state.category === "other" && !this.state.description) { - return false; - } - return true; - }, - - handleCategoryChange: function(event) { - var category = event.target.value; - this.setState({ - category: category, - description: category == "other" ? "" : this._getCategories()[category] - }); - if (category == "other") { - this.refs.description.getDOMNode().focus(); - } - }, - - handleDescriptionFieldChange: function(event) { - this.setState({description: event.target.value}); - }, - - handleDescriptionFieldFocus: function(event) { - this.setState({category: "other", description: ""}); - }, - - handleFormSubmit: function(event) { - event.preventDefault(); - this.props.sendFeedback({ - happy: false, - category: this.state.category, - description: this.state.description - }); - }, - - render: function() { - var descriptionDisplayValue = this.state.category === "other" ? - this.state.description : ""; - return ( - FeedbackLayout({title: l10n.get("feedback_what_makes_you_sad"), - reset: this.props.reset}, - React.DOM.form({onSubmit: this.handleFormSubmit}, - this._getCategoryFields(), - React.DOM.p(null, - React.DOM.input({type: "text", ref: "description", name: "description", - className: "feedback-description", - onChange: this.handleDescriptionFieldChange, - onFocus: this.handleDescriptionFieldFocus, - value: descriptionDisplayValue, - placeholder: - l10n.get("feedback_custom_category_text_placeholder")}) - ), - React.DOM.button({type: "submit", className: "btn btn-success", - disabled: !this._isFormReady()}, - l10n.get("feedback_submit_button") - ) - ) - ) - ); - } - }); - - /** - * Feedback received view. - * - * Props: - * - {Function} onAfterFeedbackReceived Function to execute after the - * WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS timeout has elapsed - */ - var FeedbackReceived = React.createClass({displayName: 'FeedbackReceived', - propTypes: { - onAfterFeedbackReceived: React.PropTypes.func - }, - - getInitialState: function() { - return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS}; - }, - - componentDidMount: function() { - this._timer = setInterval(function() { - this.setState({countdown: this.state.countdown - 1}); - }.bind(this), 1000); - }, - - componentWillUnmount: function() { - if (this._timer) { - clearInterval(this._timer); - } - }, - - render: function() { - if (this.state.countdown < 1) { - clearInterval(this._timer); - if (this.props.onAfterFeedbackReceived) { - this.props.onAfterFeedbackReceived(); - } - } - return ( - FeedbackLayout({title: l10n.get("feedback_thank_you_heading")}, - React.DOM.p({className: "info thank-you"}, - l10n.get("feedback_window_will_close_in2", { - countdown: this.state.countdown, - num: this.state.countdown - })) - ) - ); - } - }); - - /** - * Feedback view. - */ - var FeedbackView = React.createClass({displayName: 'FeedbackView', - mixins: [sharedMixins.AudioMixin], - - propTypes: { - // A loop.FeedbackAPIClient instance - feedbackApiClient: React.PropTypes.object.isRequired, - onAfterFeedbackReceived: React.PropTypes.func, - // The current feedback submission flow step name - step: React.PropTypes.oneOf(["start", "form", "finished"]) - }, - - getInitialState: function() { - return {pending: false, step: this.props.step || "start"}; - }, - - getDefaultProps: function() { - return {step: "start"}; - }, - - componentDidMount: function() { - this.play("terminated"); - }, - - reset: function() { - this.setState(this.getInitialState()); - }, - - handleHappyClick: function() { - this.sendFeedback({happy: true}, this._onFeedbackSent); - }, - - handleSadClick: function() { - this.setState({step: "form"}); - }, - - sendFeedback: function(fields) { - // Setting state.pending to true will disable the submit button to avoid - // multiple submissions - this.setState({pending: true}); - // Sends feedback data - this.props.feedbackApiClient.send(fields, this._onFeedbackSent); - }, - - _onFeedbackSent: function(err) { - if (err) { - // XXX better end user error reporting, see bug 1046738 - console.error("Unable to send user feedback", err); - } - this.setState({pending: false, step: "finished"}); - }, - - render: function() { - switch(this.state.step) { - case "finished": - return ( - FeedbackReceived({ - onAfterFeedbackReceived: this.props.onAfterFeedbackReceived}) - ); - case "form": - return FeedbackForm({feedbackApiClient: this.props.feedbackApiClient, - sendFeedback: this.sendFeedback, - reset: this.reset, - pending: this.state.pending}); - default: - return ( - FeedbackLayout({title: - l10n.get("feedback_call_experience_heading2")}, - React.DOM.div({className: "faces"}, - React.DOM.button({className: "face face-happy", - onClick: this.handleHappyClick}), - React.DOM.button({className: "face face-sad", - onClick: this.handleSadClick}) - ) - ) - ); - } - } - }); - - /** * Notification view. */ var NotificationView = React.createClass({displayName: 'NotificationView', @@ -718,12 +435,14 @@ onClick: React.PropTypes.func.isRequired, disabled: React.PropTypes.bool, additionalClass: React.PropTypes.string, + htmlId: React.PropTypes.string, }, getDefaultProps: function() { return { disabled: false, additionalClass: "", + htmlId: "", }; }, @@ -736,11 +455,12 @@ return ( React.DOM.button({onClick: this.props.onClick, disabled: this.props.disabled, + id: this.props.htmlId, className: cx(classObject)}, React.DOM.span({className: "button-caption"}, this.props.caption), this.props.children ) - ) + ); } }); @@ -765,7 +485,7 @@ React.DOM.div({className: cx(classObject)}, this.props.children ) - ) + ); } }); @@ -774,7 +494,6 @@ ButtonGroup: ButtonGroup, ConversationView: ConversationView, ConversationToolbar: ConversationToolbar, - FeedbackView: FeedbackView, MediaControlButton: MediaControlButton, NotificationListView: NotificationListView }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/views.jsx thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/views.jsx --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/js/views.jsx 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/js/views.jsx 2014-11-26 21:45:48.000000000 +0000 @@ -14,8 +14,6 @@ var sharedModels = loop.shared.models; var sharedMixins = loop.shared.mixins; - var WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS = 5; - /** * Media control button. * @@ -346,287 +344,6 @@ }); /** - * Feedback outer layout. - * - * Props: - * - - */ - var FeedbackLayout = React.createClass({ - propTypes: { - children: React.PropTypes.component.isRequired, - title: React.PropTypes.string.isRequired, - reset: React.PropTypes.func // if not specified, no Back btn is shown - }, - - render: function() { - var backButton =
; - if (this.props.reset) { - backButton = ( - - ); - } - return ( -
- {backButton} -

{this.props.title}

- {this.props.children} -
- ); - } - }); - - /** - * Detailed feedback form. - */ - var FeedbackForm = React.createClass({ - propTypes: { - pending: React.PropTypes.bool, - sendFeedback: React.PropTypes.func, - reset: React.PropTypes.func - }, - - getInitialState: function() { - return {category: "", description: ""}; - }, - - getDefaultProps: function() { - return {pending: false}; - }, - - _getCategories: function() { - return { - audio_quality: l10n.get("feedback_category_audio_quality"), - video_quality: l10n.get("feedback_category_video_quality"), - disconnected : l10n.get("feedback_category_was_disconnected"), - confusing: l10n.get("feedback_category_confusing"), - other: l10n.get("feedback_category_other") - }; - }, - - _getCategoryFields: function() { - var categories = this._getCategories(); - return Object.keys(categories).map(function(category, key) { - return ( - - ); - }, this); - }, - - /** - * Checks if the form is ready for submission: - * - * - no feedback submission should be pending. - * - a category (reason) must be chosen; - * - if the "other" category is chosen, a custom description must have been - * entered by the end user; - * - * @return {Boolean} - */ - _isFormReady: function() { - if (this.props.pending || !this.state.category) { - return false; - } - if (this.state.category === "other" && !this.state.description) { - return false; - } - return true; - }, - - handleCategoryChange: function(event) { - var category = event.target.value; - this.setState({ - category: category, - description: category == "other" ? "" : this._getCategories()[category] - }); - if (category == "other") { - this.refs.description.getDOMNode().focus(); - } - }, - - handleDescriptionFieldChange: function(event) { - this.setState({description: event.target.value}); - }, - - handleDescriptionFieldFocus: function(event) { - this.setState({category: "other", description: ""}); - }, - - handleFormSubmit: function(event) { - event.preventDefault(); - this.props.sendFeedback({ - happy: false, - category: this.state.category, - description: this.state.description - }); - }, - - render: function() { - var descriptionDisplayValue = this.state.category === "other" ? - this.state.description : ""; - return ( - -
- {this._getCategoryFields()} -

- -

- -
-
- ); - } - }); - - /** - * Feedback received view. - * - * Props: - * - {Function} onAfterFeedbackReceived Function to execute after the - * WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS timeout has elapsed - */ - var FeedbackReceived = React.createClass({ - propTypes: { - onAfterFeedbackReceived: React.PropTypes.func - }, - - getInitialState: function() { - return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS}; - }, - - componentDidMount: function() { - this._timer = setInterval(function() { - this.setState({countdown: this.state.countdown - 1}); - }.bind(this), 1000); - }, - - componentWillUnmount: function() { - if (this._timer) { - clearInterval(this._timer); - } - }, - - render: function() { - if (this.state.countdown < 1) { - clearInterval(this._timer); - if (this.props.onAfterFeedbackReceived) { - this.props.onAfterFeedbackReceived(); - } - } - return ( - -

{ - l10n.get("feedback_window_will_close_in2", { - countdown: this.state.countdown, - num: this.state.countdown - })}

-
- ); - } - }); - - /** - * Feedback view. - */ - var FeedbackView = React.createClass({ - mixins: [sharedMixins.AudioMixin], - - propTypes: { - // A loop.FeedbackAPIClient instance - feedbackApiClient: React.PropTypes.object.isRequired, - onAfterFeedbackReceived: React.PropTypes.func, - // The current feedback submission flow step name - step: React.PropTypes.oneOf(["start", "form", "finished"]) - }, - - getInitialState: function() { - return {pending: false, step: this.props.step || "start"}; - }, - - getDefaultProps: function() { - return {step: "start"}; - }, - - componentDidMount: function() { - this.play("terminated"); - }, - - reset: function() { - this.setState(this.getInitialState()); - }, - - handleHappyClick: function() { - this.sendFeedback({happy: true}, this._onFeedbackSent); - }, - - handleSadClick: function() { - this.setState({step: "form"}); - }, - - sendFeedback: function(fields) { - // Setting state.pending to true will disable the submit button to avoid - // multiple submissions - this.setState({pending: true}); - // Sends feedback data - this.props.feedbackApiClient.send(fields, this._onFeedbackSent); - }, - - _onFeedbackSent: function(err) { - if (err) { - // XXX better end user error reporting, see bug 1046738 - console.error("Unable to send user feedback", err); - } - this.setState({pending: false, step: "finished"}); - }, - - render: function() { - switch(this.state.step) { - case "finished": - return ( - - ); - case "form": - return ; - default: - return ( - -
- - -
-
- ); - } - } - }); - - /** * Notification view. */ var NotificationView = React.createClass({ @@ -718,12 +435,14 @@ onClick: React.PropTypes.func.isRequired, disabled: React.PropTypes.bool, additionalClass: React.PropTypes.string, + htmlId: React.PropTypes.string, }, getDefaultProps: function() { return { disabled: false, additionalClass: "", + htmlId: "", }; }, @@ -736,11 +455,12 @@ return ( - ) + ); } }); @@ -765,7 +485,7 @@
{this.props.children}
- ) + ); } }); @@ -774,7 +494,6 @@ ButtonGroup: ButtonGroup, ConversationView: ConversationView, ConversationToolbar: ConversationToolbar, - FeedbackView: FeedbackView, MediaControlButton: MediaControlButton, NotificationListView: NotificationListView }; Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/sounds/room-joined-in.ogg and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/sounds/room-joined-in.ogg differ Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/sounds/room-joined.ogg and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/sounds/room-joined.ogg differ Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/content/shared/sounds/room-left.ogg and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/content/shared/sounds/room-left.ogg differ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/jar.mn thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/jar.mn --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/jar.mn 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/jar.mn 2014-11-26 21:45:48.000000000 +0000 @@ -50,23 +50,35 @@ content/browser/loop/shared/img/svg/glyph-account-16x16.svg (content/shared/img/svg/glyph-account-16x16.svg) content/browser/loop/shared/img/svg/glyph-signin-16x16.svg (content/shared/img/svg/glyph-signin-16x16.svg) content/browser/loop/shared/img/svg/glyph-signout-16x16.svg (content/shared/img/svg/glyph-signout-16x16.svg) + content/browser/loop/shared/img/svg/glyph-help-16x16.svg (content/shared/img/svg/glyph-help-16x16.svg) content/browser/loop/shared/img/audio-call-avatar.svg (content/shared/img/audio-call-avatar.svg) content/browser/loop/shared/img/beta-ribbon.svg (content/shared/img/beta-ribbon.svg) content/browser/loop/shared/img/icons-10x10.svg (content/shared/img/icons-10x10.svg) content/browser/loop/shared/img/icons-14x14.svg (content/shared/img/icons-14x14.svg) content/browser/loop/shared/img/icons-16x16.svg (content/shared/img/icons-16x16.svg) + content/browser/loop/shared/img/movistar.png (content/shared/img/movistar.png) + content/browser/loop/shared/img/movistar@2x.png (content/shared/img/movistar@2x.png) + content/browser/loop/shared/img/vivo.png (content/shared/img/vivo.png) + content/browser/loop/shared/img/vivo@2x.png (content/shared/img/vivo@2x.png) + content/browser/loop/shared/img/02.png (content/shared/img/02.png) + content/browser/loop/shared/img/02@2x.png (content/shared/img/02@2x.png) + content/browser/loop/shared/img/telefonica.png (content/shared/img/telefonica.png) + content/browser/loop/shared/img/telefonica@2x.png (content/shared/img/telefonica@2x.png) # Shared scripts content/browser/loop/shared/js/actions.js (content/shared/js/actions.js) content/browser/loop/shared/js/conversationStore.js (content/shared/js/conversationStore.js) + content/browser/loop/shared/js/store.js (content/shared/js/store.js) content/browser/loop/shared/js/roomStore.js (content/shared/js/roomStore.js) content/browser/loop/shared/js/activeRoomStore.js (content/shared/js/activeRoomStore.js) + content/browser/loop/shared/js/feedbackStore.js (content/shared/js/feedbackStore.js) content/browser/loop/shared/js/dispatcher.js (content/shared/js/dispatcher.js) content/browser/loop/shared/js/feedbackApiClient.js (content/shared/js/feedbackApiClient.js) content/browser/loop/shared/js/models.js (content/shared/js/models.js) content/browser/loop/shared/js/mixins.js (content/shared/js/mixins.js) content/browser/loop/shared/js/otSdkDriver.js (content/shared/js/otSdkDriver.js) content/browser/loop/shared/js/views.js (content/shared/js/views.js) + content/browser/loop/shared/js/feedbackViews.js (content/shared/js/feedbackViews.js) content/browser/loop/shared/js/utils.js (content/shared/js/utils.js) content/browser/loop/shared/js/validate.js (content/shared/js/validate.js) content/browser/loop/shared/js/websocket.js (content/shared/js/websocket.js) @@ -82,11 +94,14 @@ content/browser/loop/shared/libs/backbone-1.1.2.js (content/shared/libs/backbone-1.1.2.js) # Shared sounds - content/browser/loop/shared/sounds/ringtone.ogg (content/shared/sounds/ringtone.ogg) - content/browser/loop/shared/sounds/connecting.ogg (content/shared/sounds/connecting.ogg) - content/browser/loop/shared/sounds/connected.ogg (content/shared/sounds/connected.ogg) - content/browser/loop/shared/sounds/terminated.ogg (content/shared/sounds/terminated.ogg) - content/browser/loop/shared/sounds/failure.ogg (content/shared/sounds/failure.ogg) + content/browser/loop/shared/sounds/ringtone.ogg (content/shared/sounds/ringtone.ogg) + content/browser/loop/shared/sounds/connecting.ogg (content/shared/sounds/connecting.ogg) + content/browser/loop/shared/sounds/connected.ogg (content/shared/sounds/connected.ogg) + content/browser/loop/shared/sounds/terminated.ogg (content/shared/sounds/terminated.ogg) + content/browser/loop/shared/sounds/room-joined.ogg (content/shared/sounds/room-joined.ogg) + content/browser/loop/shared/sounds/room-joined-in.ogg (content/shared/sounds/room-joined-in.ogg) + content/browser/loop/shared/sounds/room-left.ogg (content/shared/sounds/room-left.ogg) + content/browser/loop/shared/sounds/failure.ogg (content/shared/sounds/failure.ogg) # Partner SDK assets content/browser/loop/libs/sdk.js (content/shared/libs/sdk.js) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/LoopCalls.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/LoopCalls.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/LoopCalls.jsm 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/LoopCalls.jsm 2014-11-26 21:45:48.000000000 +0000 @@ -11,12 +11,19 @@ this.EXPORTED_SYMBOLS = ["LoopCalls"]; +const EMAIL_OR_PHONE_RE = /^(:?\S+@\S+|\+\d+)$/; + XPCOMUtils.defineLazyModuleGetter(this, "MozLoopService", "resource:///modules/loop/MozLoopService.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "LOOP_SESSION_TYPE", "resource:///modules/loop/MozLoopService.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "LoopContacts", + "resource:///modules/loop/LoopContacts.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + /** * Attempts to open a websocket. * @@ -269,7 +276,35 @@ * "outgoing". */ _startCall: function(callData) { - this.conversationInProgress.id = MozLoopService.openChatWindow(callData); + const openChat = () => { + this.conversationInProgress.id = MozLoopService.openChatWindow(callData); + }; + + if (callData.type == "incoming" && ("callerId" in callData) && + EMAIL_OR_PHONE_RE.test(callData.callerId)) { + LoopContacts.search({ + q: callData.callerId, + field: callData.callerId.contains("@") ? "email" : "tel" + }, (err, contacts) => { + if (err) { + // Database error, helas! + openChat(); + return; + } + + for (let contact of contacts) { + if (contact.blocked) { + // Blocked! Send a busy signal back to the caller. + this._returnBusy(callData); + return; + } + } + + openChat(); + }) + } else { + openChat(); + } }, /** @@ -293,6 +328,50 @@ return true; }, + /** + * Block a caller so it will show up in the contacts list as a blocked contact. + * If the contact is not yet part of the users' contacts list, it will be added + * as a blocked contact directly. + * + * @param {String} callerId Email address or phone number that may identify + * the caller as an existing contact + * @param {Function} callback Function that will be invoked once the operation + * has completed. When an error occurs, it will be + * passed as its first argument + */ + blockDirectCaller: function(callerId, callback) { + let field = callerId.contains("@") ? "email" : "tel"; + Task.spawn(function* () { + // See if we can find the caller in our database. + let contacts = yield LoopContacts.promise("search", { + q: callerId, + field: field + }); + + let contact; + if (contacts.length) { + for (contact of contacts) { + yield LoopContacts.promise("block", contact._guid); + } + } else { + // If the contact doesn't exist yet, add it as a blocked contact. + contact = { + id: MozLoopService.generateUUID(), + name: [callerId], + category: ["local"], + blocked: true + }; + // Add the phone OR email field to the contact. + contact[field] = [{ + pref: true, + value: callerId + }]; + + yield LoopContacts.promise("add", contact); + } + }).then(callback, callback); + }, + /** * Open call progress websocket and terminate with a reason of busy * the server. @@ -367,6 +446,13 @@ */ startDirectCall: function(contact, callType) { LoopCallsInternal.startDirectCall(contact, callType); + }, + + /** + * @see LoopCallsInternal#blockDirectCaller + */ + blockDirectCaller: function(callerId, callback) { + return LoopCallsInternal.blockDirectCaller(callerId, callback); } }; Object.freeze(LoopCalls); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/LoopRooms.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/LoopRooms.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/LoopRooms.jsm 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/LoopRooms.jsm 2014-11-26 21:45:48.000000000 +0000 @@ -6,6 +6,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); const {MozLoopService, LOOP_SESSION_TYPE} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); @@ -15,6 +16,9 @@ const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {}); return new EventEmitter(); }); +XPCOMUtils.defineLazyGetter(this, "gLoopBundle", function() { + return Services.strings.createBundle('chrome://browser/locale/loop/loop.properties'); +}); this.EXPORTED_SYMBOLS = ["LoopRooms", "roomsPushNotification"]; @@ -56,7 +60,11 @@ */ const containsParticipant = function(room, participant) { for (let user of room.participants) { - if (user.roomConnectionId == participant.roomConnectionId) { + // XXX until a bug 1100318 is implemented and deployed, + // we need to check the "id" field here as well - roomConnectionId is the + // official value for the interface. + if (user.roomConnectionId == participant.roomConnectionId && + user.id == participant.id) { return true; } } @@ -107,14 +115,35 @@ * violated. You'll notice this as well in the documentation for each method. */ let LoopRoomsInternal = { + /** + * @var {Map} rooms Collection of rooms currently in cache. + */ rooms: new Map(), + /** + * @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'. + */ get sessionType() { return MozLoopService.userProfile ? LOOP_SESSION_TYPE.FXA : LOOP_SESSION_TYPE.GUEST; }, /** + * @var {Number} participantsCount The total amount of participants currently + * inside all rooms. + */ + get participantsCount() { + let count = 0; + for (let room of this.rooms.values()) { + if (!("participants" in room)) { + continue; + } + count += room.participants.length; + } + return count; + }, + + /** * Fetch a list of rooms that the currently registered user is a member of. * * @param {String} [version] If set, we will fetch a list of changed rooms since @@ -131,10 +160,6 @@ } Task.spawn(function* () { - let deferredInitialization = Promise.defer(); - MozLoopService.delayedInitialize(deferredInitialization); - yield deferredInitialization.promise; - if (!gDirty) { callback(null, [...this.rooms.values()]); return; @@ -154,17 +179,21 @@ if (orig) { checkForParticipantsUpdate(orig, room); } - this.rooms.set(room.roomToken, room); - // When a version is specified, all the data is already provided by this - // request. - if (version) { - eventEmitter.emit("update", room); - eventEmitter.emit("update" + ":" + room.roomToken, room); - } else { - // Next, request the detailed information for each room. If the request - // fails the room data will not be added to the map. - yield LoopRooms.promise("get", room.roomToken); + // Remove the `currSize` for posterity. + if ("currSize" in room) { + delete room.currSize; } + this.rooms.set(room.roomToken, room); + + let eventName = orig ? "update" : "add"; + eventEmitter.emit(eventName, room); + eventEmitter.emit(eventName + ":" + room.roomToken, room); + } + + // If there's no rooms in the list, remove the guest created room flag, so that + // we don't keep registering for guest when we don't need to. + if (this.sessionType == LOOP_SESSION_TYPE.GUEST && !this.rooms.size) { + this.setGuestCreatedRoom(false); } // Set the 'dirty' flag back to FALSE, since the list is as fresh as can be now. @@ -203,11 +232,6 @@ room.roomToken = roomToken; checkForParticipantsUpdate(room, data); extend(room, data); - - // Remove the `currSize` for posterity. - if ("currSize" in room) { - delete room.currSize; - } this.rooms.set(roomToken, room); let eventName = !needsUpdate ? "update" : "add"; @@ -241,11 +265,39 @@ delete room.expiresIn; this.rooms.set(room.roomToken, room); + if (this.sessionType == LOOP_SESSION_TYPE.GUEST) { + this.setGuestCreatedRoom(true); + } + eventEmitter.emit("add", room); callback(null, room); }, error => callback(error)).catch(error => callback(error)); }, + /** + * Sets whether or not the user has created a room in guest mode. + * + * @param {Boolean} created If the user has created the room. + */ + setGuestCreatedRoom: function(created) { + if (created) { + Services.prefs.setBoolPref("loop.createdRoom", created); + } else { + Services.prefs.clearUserPref("loop.createdRoom"); + } + }, + + /** + * Returns true if the user has a created room in guest mode. + */ + getGuestCreatedRoom: function() { + try { + return Services.prefs.getBoolPref("loop.createdRoom"); + } catch (x) { + return false; + } + }, + open: function(roomToken) { let windowData = { roomToken: roomToken, @@ -303,9 +355,16 @@ * `Error` object or `null`. */ join: function(roomToken, callback) { + let displayName; + if (MozLoopService.userProfile && MozLoopService.userProfile.email) { + displayName = MozLoopService.userProfile.email; + } else { + displayName = gLoopBundle.GetStringFromName("display_name_guest"); + } + this._postToRoom(roomToken, { action: "join", - displayName: MozLoopService.userProfile.email, + displayName: displayName, clientMaxSize: CLIENT_MAX_SIZE }, callback); }, @@ -353,6 +412,34 @@ }, /** + * Renames a room. + * + * @param {String} roomToken The room token + * @param {String} newRoomName The new name for the room + * @param {Function} callback Function that will be invoked once the operation + * finished. The first argument passed will be an + * `Error` object or `null`. + */ + rename: function(roomToken, newRoomName, callback) { + let room = this.rooms.get(roomToken); + let url = "/rooms/" + encodeURIComponent(roomToken); + + let origRoom = this.rooms.get(roomToken); + let patchData = { + roomName: newRoomName, + // XXX We have to supply the max size and room owner due to bug 1099063. + maxSize: origRoom.maxSize, + roomOwner: origRoom.roomOwner + }; + MozLoopService.hawkRequest(this.sessionType, url, "PATCH", patchData) + .then(response => { + let data = JSON.parse(response.body); + extend(room, data); + callback(null, room); + }, error => callback(error)).catch(error => callback(error)); + }, + + /** * Callback used to indicate changes to rooms data on the LoopServer. * * @param {String} version Version number assigned to this change set. @@ -382,6 +469,10 @@ * See the internal code for the API documentation. */ this.LoopRooms = { + get participantsCount() { + return LoopRoomsInternal.participantsCount; + }, + getAll: function(version, callback) { return LoopRoomsInternal.getAll(version, callback); }, @@ -415,6 +506,14 @@ return LoopRoomsInternal.leave(roomToken, sessionToken, callback); }, + rename: function(roomToken, newRoomName, callback) { + return LoopRoomsInternal.rename(roomToken, newRoomName, callback); + }, + + getGuestCreatedRoom: function() { + return LoopRoomsInternal.getGuestCreatedRoom(); + }, + promise: function(method, ...params) { return new Promise((resolve, reject) => { this[method](...params, (error, result) => { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/MozLoopAPI.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/MozLoopAPI.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/MozLoopAPI.jsm 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/MozLoopAPI.jsm 2014-11-26 21:45:48.000000000 +0000 @@ -89,7 +89,15 @@ return cloneErrorObject(value, targetWindow); } - return Cu.cloneInto(value, targetWindow); + let clone; + try { + clone = Cu.cloneInto(value, targetWindow); + } catch (ex) { + MozLoopService.log.debug("Failed to clone value:", value); + throw ex; + } + + return clone; }; /** @@ -106,11 +114,18 @@ Object.keys(api).forEach(func => { injectedAPI[func] = function(...params) { let lastParam = params.pop(); + let callbackIsFunction = (typeof lastParam == "function"); // If the last parameter is a function, assume its a callback // and wrap it differently. - if (lastParam && typeof lastParam === "function") { + if (callbackIsFunction) { api[func](...params, function(...results) { + // When the function was garbage collected due to async events, like + // closing a window, we want to circumvent a JS error. + if (callbackIsFunction && typeof lastParam != "function") { + MozLoopService.log.debug(func + ": callback function was lost."); + return; + } lastParam(...[cloneValueInto(r, targetWindow) for (r of results)]); }); } else { @@ -231,7 +246,7 @@ enumerable: true, writable: true, value: function(conversationWindowId) { - return Cu.cloneInto(MozLoopService.getConversationWindowData(conversationWindowId), + return cloneValueInto(MozLoopService.getConversationWindowData(conversationWindowId), targetWindow); } }, @@ -368,32 +383,6 @@ }, /** - * Call to ensure that any necessary registrations for the Loop Service - * have taken place. - * - * Callback parameters: - * - err null on successful registration, non-null otherwise. - * - * @param {LOOP_SESSION_TYPE} sessionType - * @param {Function} callback Will be called once registration is complete, - * or straight away if registration has already - * happened. - */ - ensureRegistered: { - enumerable: true, - writable: true, - value: function(sessionType, callback) { - // We translate from a promise to a callback, as we can't pass promises from - // Promise.jsm across the priv versus unpriv boundary. - MozLoopService.promiseRegisteredWithServers(sessionType).then(() => { - callback(null); - }, err => { - callback(cloneValueInto(err, targetWindow)); - }).catch(Cu.reportError); - } - }, - - /** * Used to note a call url expiry time. If the time is later than the current * latest expiry time, then the stored expiry time is increased. For times * sooner, this function is a no-op; this ensures we always have the latest @@ -414,61 +403,41 @@ }, /** - * Set any character preference under "loop." + * Set any preference under "loop." * * @param {String} prefName The name of the pref without the preceding "loop." - * @param {String} stringValue The value to set. + * @param {*} value The value to set. + * @param {Enum} prefType Type of preference, defined at Ci.nsIPrefBranch. Optional. * * Any errors thrown by the Mozilla pref API are logged to the console * and cause false to be returned. */ - setLoopCharPref: { - enumerable: true, - writable: true, - value: function(prefName, value) { - MozLoopService.setLoopCharPref(prefName, value); - } - }, - - /** - * Return any preference under "loop." that's coercible to a character - * preference. - * - * @param {String} prefName The name of the pref without the preceding - * "loop." - * - * Any errors thrown by the Mozilla pref API are logged to the console - * and cause null to be returned. This includes the case of the preference - * not being found. - * - * @return {String} on success, null on error - */ - getLoopCharPref: { + setLoopPref: { enumerable: true, writable: true, - value: function(prefName) { - return MozLoopService.getLoopCharPref(prefName); + value: function(prefName, value, prefType) { + MozLoopService.setLoopPref(prefName, value, prefType); } }, /** - * Return any preference under "loop." that's coercible to a boolean - * preference. + * Return any preference under "loop.". * * @param {String} prefName The name of the pref without the preceding * "loop." + * @param {Enum} prefType Type of preference, defined at Ci.nsIPrefBranch. Optional. * * Any errors thrown by the Mozilla pref API are logged to the console * and cause null to be returned. This includes the case of the preference * not being found. * - * @return {String} on success, null on error + * @return {*} on success, null on error */ - getLoopBoolPref: { + getLoopPref: { enumerable: true, writable: true, - value: function(prefName) { - return MozLoopService.getLoopBoolPref(prefName); + value: function(prefName, prefType) { + return MozLoopService.getLoopPref(prefName); } }, @@ -541,9 +510,16 @@ writable: true, value: function(sessionType, path, method, payloadObj, callback) { // XXX Should really return a DOM promise here. + let callbackIsFunction = (typeof callback == "function"); MozLoopService.hawkRequest(sessionType, path, method, payloadObj).then((response) => { callback(null, response.body); }, hawkError => { + // When the function was garbage collected due to async events, like + // closing a window, we want to circumvent a JS error. + if (callbackIsFunction && typeof callback != "function") { + MozLoopService.log.debug("hawkRequest: callback function was lost."); + return; + } // The hawkError.error property, while usually a string representing // an HTTP response status message, may also incorrectly be a native // error object that will cause the cloning function to fail. @@ -596,6 +572,20 @@ }, }, + /** + * Opens the Getting Started tour in the browser. + * + * @param {String} aSrc + * - The UI element that the user used to begin the tour, optional. + */ + openGettingStartedTour: { + enumerable: true, + writable: true, + value: function(aSrc) { + return MozLoopService.openGettingStartedTour(aSrc); + }, + }, + /** * Copies passed string onto the system clipboard. * diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/MozLoopService.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/MozLoopService.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/MozLoopService.jsm 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/MozLoopService.jsm 2014-11-26 21:45:48.000000000 +0000 @@ -18,8 +18,6 @@ // See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error". const PREF_LOG_LEVEL = "loop.debug.loglevel"; -const EMAIL_OR_PHONE_RE = /^(:?\S+@\S+|\+\d+)$/; - Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); @@ -81,6 +79,10 @@ "@mozilla.org/network/dns-service;1", "nsIDNSService"); +XPCOMUtils.defineLazyServiceGetter(this, "gWM", + "@mozilla.org/appshell/window-mediator;1", + "nsIWindowMediator"); + // Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref. XPCOMUtils.defineLazyGetter(this, "log", () => { let ConsoleAPI = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).ConsoleAPI; @@ -102,7 +104,7 @@ } let gHawkClient = null; -let gLocalizedStrings = null; +let gLocalizedStrings = new Map(); let gFxAEnabled = true; let gFxAOAuthClientPromise = null; let gFxAOAuthClient = null; @@ -291,12 +293,12 @@ messageString = "generic_failure_title"; } - error.friendlyMessage = this.localizedStrings[messageString].textContent; + error.friendlyMessage = this.localizedStrings.get(messageString); error.friendlyDetails = detailsString ? - this.localizedStrings[detailsString].textContent : + this.localizedStrings.get(detailsString) : null; error.friendlyDetailsButtonLabel = detailsButtonLabelString ? - this.localizedStrings[detailsButtonLabelString].textContent : + this.localizedStrings.get(detailsButtonLabelString) : null; error.friendlyDetailsButtonCallback = actionCallback || detailsButtonCallback || null; @@ -326,8 +328,8 @@ */ promiseRegisteredWithPushServer: function(sessionType) { if (!this.deferredRegistrations.has(sessionType)) { - return Promise.reject("promiseRegisteredWithPushServer must be called while there is a " + - "deferred in deferredRegistrations in order to prevent reentrancy"); + return Promise.reject(new Error("promiseRegisteredWithPushServer must be called while there is a " + + "deferred in deferredRegistrations in order to prevent reentrancy")); } // Wrap push notification registration call-back in a Promise. function registerForNotification(channelID, onNotification) { @@ -373,7 +375,7 @@ return Promise.all([callsRegFxA, roomsRegFxA]); } - return Promise.reject("promiseRegisteredWithPushServer: Invalid sessionType"); + return Promise.reject(new Error("promiseRegisteredWithPushServer: Invalid sessionType")); }, /** @@ -415,7 +417,8 @@ }, /** - * Performs a hawk based request to the loop server. + * Performs a hawk based request to the loop server - there is no pre-registration + * for this request, if this is required, use hawkRequest. * * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request. * This is one of the LOOP_SESSION_TYPE members. @@ -429,8 +432,7 @@ * as JSON and contains an 'error' property, the promise will be * rejected with this JSON-parsed response. */ - hawkRequest: function(sessionType, path, method, payloadObj) { - log.debug("hawkRequest: " + path, sessionType); + hawkRequestInternal: function(sessionType, path, method, payloadObj) { if (!gHawkClient) { gHawkClient = new HawkClient(this.loopServerUri); } @@ -476,6 +478,32 @@ }, /** + * Performs a hawk based request to the loop server, registering if necessary. + * + * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request. + * This is one of the LOOP_SESSION_TYPE members. + * @param {String} path The path to make the request to. + * @param {String} method The request method, e.g. 'POST', 'GET'. + * @param {Object} payloadObj An object which is converted to JSON and + * transmitted with the request. + * @returns {Promise} + * Returns a promise that resolves to the response of the API call, + * or is rejected with an error. If the server response can be parsed + * as JSON and contains an 'error' property, the promise will be + * rejected with this JSON-parsed response. + */ + hawkRequest: function(sessionType, path, method, payloadObj) { + log.debug("hawkRequest: " + path, sessionType); + return new Promise((resolve, reject) => { + MozLoopService.promiseRegisteredWithServers(sessionType).then(() => { + this.hawkRequestInternal(sessionType, path, method, payloadObj).then(resolve, reject); + }, err => { + reject(err); + }).catch(reject); + }); + }, + + /** * Generic hawkRequest onError handler for the hawkRequest promise. * * @param {Object} error - error reporting object @@ -565,7 +593,7 @@ } if (!callsPushURL || !roomsPushURL) { - return Promise.reject("Invalid sessionType or missing push URLs for registerWithLoopServer: " + sessionType); + return Promise.reject(new Error("Invalid sessionType or missing push URLs for registerWithLoopServer: " + sessionType)); } // create a registration payload with a backwards compatible attribute (simplePushURL) @@ -577,11 +605,11 @@ rooms: roomsPushURL, }, }; - return this.hawkRequest(sessionType, "/registration", "POST", msg) + return this.hawkRequestInternal(sessionType, "/registration", "POST", msg) .then((response) => { // If this failed we got an invalid token. if (!this.storeSessionToken(sessionType, response.headers)) { - return Promise.reject("session-token-wrong-size"); + return Promise.reject(new Error("session-token-wrong-size")); } log.debug("Successfully registered with server for sessionType", sessionType); @@ -633,7 +661,7 @@ } let unregisterURL = "/registration?simplePushURL=" + encodeURIComponent(pushURL); - return this.hawkRequest(sessionType, unregisterURL, "DELETE") + return this.hawkRequestInternal(sessionType, unregisterURL, "DELETE") .then(() => { log.debug("Successfully unregistered from server for sessionType", sessionType); }, @@ -652,33 +680,22 @@ * A getter to obtain and store the strings for loop. This is structured * for use by l10n.js. * - * @returns {Object} a map of element ids with attributes to set. + * @returns {Map} a map of element ids with localized string values */ get localizedStrings() { - if (gLocalizedStrings) + if (gLocalizedStrings.size) return gLocalizedStrings; - var stringBundle = - Services.strings.createBundle('chrome://browser/locale/loop/loop.properties'); + let stringBundle = + Services.strings.createBundle("chrome://browser/locale/loop/loop.properties"); - var map = {}; - var enumerator = stringBundle.getSimpleEnumeration(); + let enumerator = stringBundle.getSimpleEnumeration(); while (enumerator.hasMoreElements()) { - var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); - - // 'textContent' is the default attribute to set if none are specified. - var key = string.key, property = 'textContent'; - var i = key.lastIndexOf('.'); - if (i >= 0) { - property = key.substring(i + 1); - key = key.substring(0, i); - } - if (!(key in map)) - map[key] = {}; - map[key][property] = string.value; + let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); + gLocalizedStrings.set(string.key, string.value); } - return gLocalizedStrings = map; + return gLocalizedStrings; }, /** @@ -757,7 +774,14 @@ openChatWindow: function(conversationWindowData) { // So I guess the origin is the loop server!? let origin = this.loopServerUri; - let windowId = gLastWindowId++; + // Try getting a window ID that can (re-)identify this conversation, or resort + // to a globally unique one as a last resort. + // XXX We can clean this up once rooms and direct contact calling are the only + // two modes left. + let windowId = ("contact" in conversationWindowData) ? + conversationWindowData.contact._guid || gLastWindowId++ : + conversationWindowData.roomToken || conversationWindowData.callId || + gLastWindowId++; // Store the id as a string, as that's what we use elsewhere. windowId = windowId.toString(); @@ -822,7 +846,7 @@ */ promiseFxAOAuthParameters: function() { const SESSION_TYPE = LOOP_SESSION_TYPE.FXA; - return this.hawkRequest(SESSION_TYPE, "/fxa-oauth/params", "POST").then(response => { + return this.hawkRequestInternal(SESSION_TYPE, "/fxa-oauth/params", "POST").then(response => { if (!this.storeSessionToken(SESSION_TYPE, response.headers)) { throw new Error("Invalid FxA hawk token returned"); } @@ -965,6 +989,10 @@ gInitializeTimerFunc = value; }, + get roomsParticipantsCount() { + return LoopRooms.participantsCount; + }, + /** * Initialized the loop service, and starts registration with the * push and loop servers. @@ -985,7 +1013,7 @@ // Don't do anything if loop is not enabled. if (!Services.prefs.getBoolPref("loop.enabled")) { - return Promise.reject("loop is not enabled"); + return Promise.reject(new Error("loop is not enabled")); } if (Services.prefs.getPrefType("loop.fxa.enabled") == Services.prefs.PREF_BOOL) { @@ -995,9 +1023,30 @@ } } + // The Loop toolbar button should change icon when the room participant count + // changes from 0 to something. + const onRoomsChange = () => { + MozLoopServiceInternal.notifyStatusChanged(); + }; + LoopRooms.on("add", onRoomsChange); + LoopRooms.on("update", onRoomsChange); + LoopRooms.on("joined", (e, roomToken, participant) => { + // Don't alert if we're in the doNotDisturb mode, or the participant + // is the owner - the content code deals with the rest of the sounds. + if (MozLoopServiceInternal.doNotDisturb || participant.owner) { + return; + } + + let window = gWM.getMostRecentWindow("navigator:browser"); + if (window) { + window.LoopUI.playSound("room-joined"); + } + }); + // If expiresTime is not in the future and the user hasn't // previously authenticated then skip registration. if (!MozLoopServiceInternal.urlExpiryTimeIsInFuture() && + !LoopRooms.getGuestCreatedRoom() && !MozLoopServiceInternal.fxAOAuthTokenData) { return Promise.resolve("registration not needed"); } @@ -1031,7 +1080,8 @@ }); try { - if (MozLoopServiceInternal.urlExpiryTimeIsInFuture()) { + if (MozLoopServiceInternal.urlExpiryTimeIsInFuture() || + LoopRooms.getGuestCreatedRoom()) { yield this.promiseRegisteredWithServers(LOOP_SESSION_TYPE.GUEST); } else { log.debug("delayedInitialize: URL expiry time isn't in the future so not registering as a guest"); @@ -1096,21 +1146,20 @@ }, /** - * Returns the strings for the specified element. Designed for use - * with l10n.js. + * Returns the strings for the specified element. Designed for use with l10n.js. * * @param {key} The element id to get strings for. - * @return {String} A JSON string containing the localized - * attribute/value pairs for the element. + * @return {String} A JSON string containing the localized attribute/value pairs + * for the element. */ getStrings: function(key) { - var stringData = MozLoopServiceInternal.localizedStrings; - if (!(key in stringData)) { - log.error("No string found for key: ", key); - return ""; - } + var stringData = MozLoopServiceInternal.localizedStrings; + if (!stringData.has(key)) { + log.error("No string found for key: ", key); + return ""; + } - return JSON.stringify(stringData[key]); + return JSON.stringify({ textContent: stringData.get(key) }); }, /** @@ -1192,63 +1241,75 @@ }, /** - * Set any character preference under "loop.". + * Set any preference under "loop.". * - * @param {String} prefName The name of the pref without the preceding "loop." - * @param {String} value The value to set. + * @param {String} prefSuffix The name of the pref without the preceding "loop." + * @param {*} value The value to set. + * @param {Enum} prefType Type of preference, defined at Ci.nsIPrefBranch. Optional. * * Any errors thrown by the Mozilla pref API are logged to the console. */ - setLoopCharPref: function(prefName, value) { + setLoopPref: function(prefSuffix, value, prefType) { + let prefName = "loop." + prefSuffix; try { - Services.prefs.setCharPref("loop." + prefName, value); - } catch (ex) { - log.error("setLoopCharPref had trouble setting " + prefName + - "; exception: " + ex); - } - }, - - /** - * Return any preference under "loop." that's coercible to a character - * preference. - * - * @param {String} prefName The name of the pref without the preceding - * "loop." - * - * Any errors thrown by the Mozilla pref API are logged to the console - * and cause null to be returned. This includes the case of the preference - * not being found. - * - * @return {String} on success, null on error - */ - getLoopCharPref: function(prefName) { - try { - return Services.prefs.getCharPref("loop." + prefName); + if (!prefType) { + prefType = Services.prefs.getPrefType(prefName); + } + switch (prefType) { + case Ci.nsIPrefBranch.PREF_STRING: + Services.prefs.setCharPref(prefName, value); + break; + case Ci.nsIPrefBranch.PREF_INT: + Services.prefs.setIntPref(prefName, value); + break; + case Ci.nsIPrefBranch.PREF_BOOL: + Services.prefs.setBoolPref(prefName, value); + break; + default: + log.error("invalid preference type setting " + prefName); + break; + } } catch (ex) { - log.error("getLoopCharPref had trouble getting " + prefName + + log.error("setLoopPref had trouble setting " + prefName + "; exception: " + ex); - return null; } }, /** - * Return any preference under "loop." that's coercible to a character - * preference. + * Return any preference under "loop.". * * @param {String} prefName The name of the pref without the preceding * "loop." + * @param {Enum} prefType Type of preference, defined at Ci.nsIPrefBranch. Optional. * * Any errors thrown by the Mozilla pref API are logged to the console * and cause null to be returned. This includes the case of the preference * not being found. * - * @return {String} on success, null on error + * @return {*} on success, null on error */ - getLoopBoolPref: function(prefName) { + getLoopPref: function(prefSuffix, prefType) { + let prefName = "loop." + prefSuffix; try { - return Services.prefs.getBoolPref("loop." + prefName); + if (!prefType) { + prefType = Services.prefs.getPrefType(prefName); + } else if (prefType != Services.prefs.getPrefType(prefName)) { + log.error("invalid type specified for preference"); + return null; + } + switch (prefType) { + case Ci.nsIPrefBranch.PREF_STRING: + return Services.prefs.getCharPref(prefName); + case Ci.nsIPrefBranch.PREF_INT: + return Services.prefs.getIntPref(prefName); + case Ci.nsIPrefBranch.PREF_BOOL: + return Services.prefs.getBoolPref(prefName); + default: + log.error("invalid preference type getting " + prefName); + return null; + } } catch (ex) { - log.error("getLoopBoolPref had trouble getting " + prefName + + log.error("getLoopPref had trouble getting " + prefName + "; exception: " + ex); return null; } @@ -1359,6 +1420,28 @@ } }), + /** + * Opens the Getting Started tour in the browser. + * + * @param {String} aSrc + * - The UI element that the user used to begin the tour, optional. + */ + openGettingStartedTour: Task.async(function(aSrc = null) { + try { + let urlStr = Services.prefs.getCharPref("loop.gettingStarted.url"); + let url = new URL(Services.urlFormatter.formatURL(urlStr)); + if (aSrc) { + url.searchParams.set("utm_source", "firefox-browser"); + url.searchParams.set("utm_medium", "firefox-browser"); + url.searchParams.set("utm_campaign", aSrc); + } + let win = Services.wm.getMostRecentWindow("navigator:browser"); + win.switchToTabHavingURI(url, true, {replaceQueryString: true}); + } catch (ex) { + log.error("Error opening Getting Started tour", ex); + } + }), + /** * Performs a hawk based request to the loop server. * diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/css/webapp.css thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/css/webapp.css --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/css/webapp.css 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/css/webapp.css 2014-11-26 21:45:48.000000000 +0000 @@ -18,6 +18,13 @@ font-family: Open Sans,sans-serif; } +/** + * Note: the is-standalone-room class is dynamically set by the StandaloneRoomView. + */ +.standalone.is-standalone-room { + background-color: #000; +} + .standalone-header { border-radius: 4px; background: #fff; @@ -80,15 +87,19 @@ color: #777; } -.footer-external-links a { +.footer-external-links { padding: .2rem .7rem; +} + +.footer-external-links a { margin: 0 .5rem; text-decoration: none; + color: #adadad; } - .footer-external-links a:hover { - color: #111; - } +.footer-external-links a:hover { + color: #777; +} .footer-logo { width: 100px; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/index.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/index.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/index.html 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/index.html 2014-11-26 21:45:48.000000000 +0000 @@ -5,14 +5,14 @@ + + + - - - - + @@ -42,7 +42,7 @@ myCustomEvent.prototype = window.Event.prototype; window.CustomEvent = myCustomEvent; } - + // To support IE for the l10n-gaia library on IE <= 10. if (!"language" in navigator) { navigator.language = navigator.browserLanguage; @@ -97,7 +97,10 @@ + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/standaloneMozLoop.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/standaloneMozLoop.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/standaloneMozLoop.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/standaloneMozLoop.js 2014-11-26 21:45:48.000000000 +0000 @@ -170,7 +170,13 @@ action: "leave", sessionToken: sessionToken }, null, callback); - } + }, + + // Dummy functions to reflect those in the desktop mozLoop.rooms that we + // don't currently use. + on: function() {}, + once: function() {}, + off: function() {} }; var StandaloneMozLoop = function(options) { @@ -184,5 +190,33 @@ this.rooms = new StandaloneMozLoopRooms(options); }; + StandaloneMozLoop.prototype = { + /** + * Stores a preference in the local storage for standalone. + * Note: Some prefs are filtered out as they are not applicable + * to the standalone UI. + * + * @param {String} prefName The name of the pref + * @param {String} value The value to set. + */ + setLoopPref: function(prefName, value) { + if (prefName === "seenToS") { + return; + } + + localStorage.setItem(prefName, value); + }, + + /** + * Gets a preference from the local storage for standalone. + * + * @param {String} prefName The name of the pref + * @param {String} value The value to set. + */ + getLoopPref: function(prefName) { + return localStorage.getItem(prefName); + } + }; + return StandaloneMozLoop; })(navigator.mozL10n); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.js 2014-11-26 21:45:48.000000000 +0000 @@ -11,8 +11,10 @@ loop.standaloneRoomViews = (function(mozL10n) { "use strict"; + var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS; var ROOM_STATES = loop.store.ROOM_STATES; var sharedActions = loop.shared.actions; + var sharedMixins = loop.shared.mixins; var sharedViews = loop.shared.views; var StandaloneRoomInfoArea = React.createClass({displayName: 'StandaloneRoomInfoArea', @@ -39,10 +41,26 @@ ); }, + /** + * @return String An appropriate string according to the failureReason. + */ + _getFailureString: function() { + switch(this.props.failureReason) { + case FAILURE_REASONS.MEDIA_DENIED: + return mozL10n.get("rooms_media_denied_message"); + case FAILURE_REASONS.EXPIRED_OR_INVALID: + return mozL10n.get("rooms_unavailable_notification_message"); + default: + return mozL10n.get("status_error"); + } + }, + _renderContent: function() { switch(this.props.roomState) { case ROOM_STATES.INIT: - case ROOM_STATES.READY: { + case ROOM_STATES.READY: + case ROOM_STATES.ENDED: { + // XXX: In ENDED state, we should rather display the feedback form. return ( React.DOM.button({className: "btn btn-join btn-info", onClick: this.props.joinRoom}, @@ -67,6 +85,12 @@ React.DOM.p(null, this._renderCallToActionLink()) ) ); + case ROOM_STATES.FAILED: + return ( + React.DOM.p({className: "failed-room-message"}, + this._getFailureString() + ) + ); default: return null; } @@ -81,8 +105,51 @@ } }); + var StandaloneRoomHeader = React.createClass({displayName: 'StandaloneRoomHeader', + render: function() { + return ( + React.DOM.header(null, + React.DOM.h1(null, mozL10n.get("clientShortname2")), + React.DOM.a({target: "_blank", href: loop.config.roomsSupportUrl}, + React.DOM.i({className: "icon icon-help"}) + ) + ) + ); + } + }); + + var StandaloneRoomFooter = React.createClass({displayName: 'StandaloneRoomFooter', + _getContent: function() { + return mozL10n.get("legal_text_and_links", { + "clientShortname": mozL10n.get("clientShortname2"), + "terms_of_use_url": React.renderComponentToStaticMarkup( + React.DOM.a({href: loop.config.legalWebsiteUrl, target: "_blank"}, + mozL10n.get("terms_of_use_link_text") + ) + ), + "privacy_notice_url": React.renderComponentToStaticMarkup( + React.DOM.a({href: loop.config.privacyWebsiteUrl, target: "_blank"}, + mozL10n.get("privacy_notice_link_text") + ) + ), + }); + }, + + render: function() { + return ( + React.DOM.footer(null, + React.DOM.p({dangerouslySetInnerHTML: {__html: this._getContent()}}), + React.DOM.div({className: "footer-logo"}) + ) + ); + } + }); + var StandaloneRoomView = React.createClass({displayName: 'StandaloneRoomView', - mixins: [Backbone.Events], + mixins: [ + Backbone.Events, + sharedMixins.RoomsAudioMixin + ], propTypes: { activeRoomStore: @@ -144,18 +211,24 @@ }; }, + componentDidMount: function() { + // Adding a class to the document body element from here to ease styling it. + document.body.classList.add("is-standalone-room"); + }, + componentWillUnmount: function() { this.stopListening(this.props.activeRoomStore); }, /** - * Watches for when we transition from READY to JOINED room state, so we can - * request user media access. + * Watches for when we transition to JOINED room state, so we can request + * user media access. + * * @param {Object} nextProps (Unused) * @param {Object} nextState Next state object. */ componentWillUpdate: function(nextProps, nextState) { - if (this.state.roomState === ROOM_STATES.READY && + if (this.state.roomState !== ROOM_STATES.JOINED && nextState.roomState === ROOM_STATES.JOINED) { this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ publisherConfig: this._getPublisherConfig(), @@ -207,7 +280,9 @@ return ( React.DOM.div({className: "room-conversation-wrapper"}, + StandaloneRoomHeader(null), StandaloneRoomInfoArea({roomState: this.state.roomState, + failureReason: this.state.failureReason, joinRoom: this.joinRoom, helper: this.props.helper}), React.DOM.div({className: "video-layout-wrapper"}, @@ -229,7 +304,8 @@ hangupButtonLabel: mozL10n.get("rooms_leave_button_label"), enableHangup: this._roomIsActive()}) ) - ) + ), + StandaloneRoomFooter(null) ) ); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx 2014-11-26 21:45:48.000000000 +0000 @@ -11,8 +11,10 @@ loop.standaloneRoomViews = (function(mozL10n) { "use strict"; + var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS; var ROOM_STATES = loop.store.ROOM_STATES; var sharedActions = loop.shared.actions; + var sharedMixins = loop.shared.mixins; var sharedViews = loop.shared.views; var StandaloneRoomInfoArea = React.createClass({ @@ -39,10 +41,26 @@ ); }, + /** + * @return String An appropriate string according to the failureReason. + */ + _getFailureString: function() { + switch(this.props.failureReason) { + case FAILURE_REASONS.MEDIA_DENIED: + return mozL10n.get("rooms_media_denied_message"); + case FAILURE_REASONS.EXPIRED_OR_INVALID: + return mozL10n.get("rooms_unavailable_notification_message"); + default: + return mozL10n.get("status_error"); + } + }, + _renderContent: function() { switch(this.props.roomState) { case ROOM_STATES.INIT: - case ROOM_STATES.READY: { + case ROOM_STATES.READY: + case ROOM_STATES.ENDED: { + // XXX: In ENDED state, we should rather display the feedback form. return (
); + case ROOM_STATES.FAILED: + return ( +

+ {this._getFailureString()} +

+ ); default: return null; } @@ -81,8 +105,51 @@ } }); + var StandaloneRoomHeader = React.createClass({ + render: function() { + return ( +
+

{mozL10n.get("clientShortname2")}

+ + + +
+ ); + } + }); + + var StandaloneRoomFooter = React.createClass({ + _getContent: function() { + return mozL10n.get("legal_text_and_links", { + "clientShortname": mozL10n.get("clientShortname2"), + "terms_of_use_url": React.renderComponentToStaticMarkup( + + {mozL10n.get("terms_of_use_link_text")} + + ), + "privacy_notice_url": React.renderComponentToStaticMarkup( + + {mozL10n.get("privacy_notice_link_text")} + + ), + }); + }, + + render: function() { + return ( +
+

+
+
+ ); + } + }); + var StandaloneRoomView = React.createClass({ - mixins: [Backbone.Events], + mixins: [ + Backbone.Events, + sharedMixins.RoomsAudioMixin + ], propTypes: { activeRoomStore: @@ -144,18 +211,24 @@ }; }, + componentDidMount: function() { + // Adding a class to the document body element from here to ease styling it. + document.body.classList.add("is-standalone-room"); + }, + componentWillUnmount: function() { this.stopListening(this.props.activeRoomStore); }, /** - * Watches for when we transition from READY to JOINED room state, so we can - * request user media access. + * Watches for when we transition to JOINED room state, so we can request + * user media access. + * * @param {Object} nextProps (Unused) * @param {Object} nextState Next state object. */ componentWillUpdate: function(nextProps, nextState) { - if (this.state.roomState === ROOM_STATES.READY && + if (this.state.roomState !== ROOM_STATES.JOINED && nextState.roomState === ROOM_STATES.JOINED) { this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ publisherConfig: this._getPublisherConfig(), @@ -207,7 +280,9 @@ return (
+
@@ -230,6 +305,7 @@ enableHangup={this._roomIsActive()} />
+ ); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/webapp.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/webapp.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/webapp.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/webapp.js 2014-11-26 21:45:48.000000000 +0000 @@ -259,13 +259,91 @@ React.DOM.div({className: "standalone-footer container-box"}, React.DOM.div({title: mozL10n.get("vendor_alttext", {vendorShortname: mozL10n.get("vendorShortname")}), - className: "footer-logo"}) + className: "footer-logo"}), + React.DOM.div({className: "footer-external-links"}, + React.DOM.a({target: "_blank", href: loop.config.guestSupportUrl}, + mozL10n.get("support_link") + ) + ) ) ); } }); + /** + * A view for when conversations are pending, displays any messages + * and an option cancel button. + */ var PendingConversationView = React.createClass({displayName: 'PendingConversationView', + propTypes: { + callState: React.PropTypes.string.isRequired, + // If not supplied, the cancel button is not displayed. + cancelCallback: React.PropTypes.func + }, + + render: function() { + var cancelButtonClasses = React.addons.classSet({ + btn: true, + "btn-large": true, + "btn-cancel": true, + hide: !this.props.cancelCallback + }); + + return ( + React.DOM.div({className: "container"}, + React.DOM.div({className: "container-box"}, + React.DOM.header({className: "pending-header header-box"}, + ConversationBranding(null) + ), + + React.DOM.div({id: "cameraPreview"}), + + React.DOM.div({id: "messages"}), + + React.DOM.p({className: "standalone-btn-label"}, + this.props.callState + ), + + React.DOM.div({className: "btn-pending-cancel-group btn-group"}, + React.DOM.div({className: "flex-padding-1"}), + React.DOM.button({className: cancelButtonClasses, + onClick: this.props.cancelCallback}, + React.DOM.span({className: "standalone-call-btn-text"}, + mozL10n.get("initiate_call_cancel_button") + ) + ), + React.DOM.div({className: "flex-padding-1"}) + ) + ), + ConversationFooter(null) + ) + ); + } + }); + + /** + * View displayed whilst the get user media prompt is being displayed. Indicates + * to the user to accept the prompt. + */ + var GumPromptConversationView = React.createClass({displayName: 'GumPromptConversationView', + render: function() { + var callState = mozL10n.get("call_progress_getting_media_description", { + clientShortname: mozL10n.get("clientShortname2") + }); + document.title = mozL10n.get("standalone_title_with_status", { + clientShortname: mozL10n.get("clientShortname2"), + currentStatus: mozL10n.get("call_progress_getting_media_title") + }); + + return PendingConversationView({callState: callState}); + } + }); + + /** + * View displayed waiting for a call to be connected. Updates the display + * once the websocket shows that the callee is being alerted. + */ + var WaitingConversationView = React.createClass({displayName: 'WaitingConversationView', mixins: [sharedMixins.AudioMixin], getInitialState: function() { @@ -301,33 +379,11 @@ document.title = mozL10n.get("standalone_title_with_status", {clientShortname: mozL10n.get("clientShortname2"), currentStatus: mozL10n.get(callStateStringEntityName)}); - return ( - React.DOM.div({className: "container"}, - React.DOM.div({className: "container-box"}, - React.DOM.header({className: "pending-header header-box"}, - ConversationBranding(null) - ), - - React.DOM.div({id: "cameraPreview"}), - - React.DOM.div({id: "messages"}), - React.DOM.p({className: "standalone-btn-label"}, - callState - ), - - React.DOM.div({className: "btn-pending-cancel-group btn-group"}, - React.DOM.div({className: "flex-padding-1"}), - React.DOM.button({className: "btn btn-large btn-cancel", - onClick: this._cancelOutgoingCall}, - React.DOM.span({className: "standalone-call-btn-text"}, - mozL10n.get("initiate_call_cancel_button") - ) - ), - React.DOM.div({className: "flex-padding-1"}) - ) - ), - ConversationFooter(null) + return ( + PendingConversationView({ + callState: callState, + cancelCallback: this._cancelOutgoingCall} ) ); } @@ -453,15 +509,8 @@ */ startCall: function(callType) { return function() { - multiplexGum.getPermsAndCacheMedia({audio:true, video:true}, - function(localStream) { - this.props.conversation.setupOutgoingCall(callType); - this.setState({disableCallButton: true}); - }.bind(this), - function(errorCode) { - multiplexGum.reset(); - }.bind(this) - ); + this.props.conversation.setupOutgoingCall(callType); + this.setState({disableCallButton: true}); }.bind(this); }, @@ -538,7 +587,7 @@ conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackApiClient: React.PropTypes.object.isRequired, + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), onAfterFeedbackReceived: React.PropTypes.func.isRequired }, @@ -549,7 +598,7 @@ return ( React.DOM.div({className: "ended-conversation"}, sharedViews.FeedbackView({ - feedbackApiClient: this.props.feedbackApiClient, + feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.props.onAfterFeedbackReceived} ), sharedViews.ConversationView({ @@ -611,7 +660,7 @@ notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackApiClient: React.PropTypes.object.isRequired + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) }, getInitialState: function() { @@ -622,6 +671,7 @@ componentDidMount: function() { this.props.conversation.on("call:outgoing", this.startCall, this); + this.props.conversation.on("call:outgoing:get-media-privs", this.getMediaPrivs, this); this.props.conversation.on("call:outgoing:setup", this.setupOutgoingCall, this); this.props.conversation.on("change:publishedStream", this._checkConnected, this); this.props.conversation.on("change:subscribedStream", this._checkConnected, this); @@ -669,8 +719,11 @@ ) ); } + case "gumPrompt": { + return GumPromptConversationView(null); + } case "pending": { - return PendingConversationView({websocket: this._websocket}); + return WaitingConversationView({websocket: this._websocket}); } case "connected": { document.title = mozL10n.get("standalone_title_with_status", @@ -690,7 +743,7 @@ EndedConversationView({ sdk: this.props.sdk, conversation: this.props.conversation, - feedbackApiClient: this.props.feedbackApiClient, + feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.callStatusSwitcher("start")} ) ); @@ -770,6 +823,22 @@ }, /** + * Asks the user for the media privileges, handling the result appropriately. + */ + getMediaPrivs: function() { + this.setState({callStatus: "gumPrompt"}); + multiplexGum.getPermsAndCacheMedia({audio:true, video:true}, + function(localStream) { + this.props.conversation.gotMediaPrivs(); + }.bind(this), + function(errorCode) { + multiplexGum.reset(); + this.setState({callStatus: "failure"}); + }.bind(this) + ); + }, + + /** * Actually starts the call. */ startCall: function() { @@ -861,6 +930,8 @@ * Handles ending a call by resetting the view to the start state. */ _endCall: function() { + multiplexGum.reset(); + if (this.state.callStatus !== "failure") { this.setState({callStatus: "end"}); } @@ -887,14 +958,14 @@ notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackApiClient: React.PropTypes.object.isRequired, // XXX New types for flux style standaloneAppStore: React.PropTypes.instanceOf( loop.store.StandaloneAppStore).isRequired, activeRoomStore: React.PropTypes.instanceOf( loop.store.ActiveRoomStore).isRequired, - dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) }, getInitialState: function() { @@ -931,7 +1002,7 @@ helper: this.props.helper, notifications: this.props.notifications, sdk: this.props.sdk, - feedbackApiClient: this.props.feedbackApiClient} + feedbackStore: this.props.feedbackStore} ) ); } @@ -992,18 +1063,27 @@ dispatcher: dispatcher, sdk: OT }); + var feedbackClient = new loop.FeedbackAPIClient( + loop.config.feedbackApiUrl, { + product: loop.config.feedbackProductName, + user_agent: navigator.userAgent, + url: document.location.origin + }); + // Stores var standaloneAppStore = new loop.store.StandaloneAppStore({ conversation: conversation, dispatcher: dispatcher, helper: helper, sdk: OT }); - var activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: standaloneMozLoop, sdkDriver: sdkDriver }); + var feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: feedbackClient + }); window.addEventListener("unload", function() { dispatcher.dispatch(new sharedActions.WindowUnload()); @@ -1015,7 +1095,7 @@ helper: helper, notifications: notifications, sdk: OT, - feedbackApiClient: feedbackApiClient, + feedbackStore: feedbackStore, standaloneAppStore: standaloneAppStore, activeRoomStore: activeRoomStore, dispatcher: dispatcher} @@ -1036,6 +1116,8 @@ return { CallUrlExpiredView: CallUrlExpiredView, PendingConversationView: PendingConversationView, + GumPromptConversationView: GumPromptConversationView, + WaitingConversationView: WaitingConversationView, StartConversationView: StartConversationView, FailedConversationView: FailedConversationView, OutgoingConversationView: OutgoingConversationView, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/webapp.jsx thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/webapp.jsx --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/js/webapp.jsx 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/js/webapp.jsx 2014-11-26 21:45:48.000000000 +0000 @@ -260,12 +260,90 @@
+ ); } }); + /** + * A view for when conversations are pending, displays any messages + * and an option cancel button. + */ var PendingConversationView = React.createClass({ + propTypes: { + callState: React.PropTypes.string.isRequired, + // If not supplied, the cancel button is not displayed. + cancelCallback: React.PropTypes.func + }, + + render: function() { + var cancelButtonClasses = React.addons.classSet({ + btn: true, + "btn-large": true, + "btn-cancel": true, + hide: !this.props.cancelCallback + }); + + return ( +
+
+
+ +
+ +
+ +
+ +

+ {this.props.callState} +

+ +
+
+ +
+
+
+ +
+ ); + } + }); + + /** + * View displayed whilst the get user media prompt is being displayed. Indicates + * to the user to accept the prompt. + */ + var GumPromptConversationView = React.createClass({ + render: function() { + var callState = mozL10n.get("call_progress_getting_media_description", { + clientShortname: mozL10n.get("clientShortname2") + }); + document.title = mozL10n.get("standalone_title_with_status", { + clientShortname: mozL10n.get("clientShortname2"), + currentStatus: mozL10n.get("call_progress_getting_media_title") + }); + + return ; + } + }); + + /** + * View displayed waiting for a call to be connected. Updates the display + * once the websocket shows that the callee is being alerted. + */ + var WaitingConversationView = React.createClass({ mixins: [sharedMixins.AudioMixin], getInitialState: function() { @@ -301,34 +379,12 @@ document.title = mozL10n.get("standalone_title_with_status", {clientShortname: mozL10n.get("clientShortname2"), currentStatus: mozL10n.get(callStateStringEntityName)}); - return ( -
-
-
- -
- -
-
- -

- {callState} -

- -
-
- -
-
-
- -
+ return ( + ); } }); @@ -453,15 +509,8 @@ */ startCall: function(callType) { return function() { - multiplexGum.getPermsAndCacheMedia({audio:true, video:true}, - function(localStream) { - this.props.conversation.setupOutgoingCall(callType); - this.setState({disableCallButton: true}); - }.bind(this), - function(errorCode) { - multiplexGum.reset(); - }.bind(this) - ); + this.props.conversation.setupOutgoingCall(callType); + this.setState({disableCallButton: true}); }.bind(this); }, @@ -538,7 +587,7 @@ conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackApiClient: React.PropTypes.object.isRequired, + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), onAfterFeedbackReceived: React.PropTypes.func.isRequired }, @@ -549,7 +598,7 @@ return (
); } + case "gumPrompt": { + return ; + } case "pending": { - return ; + return ; } case "connected": { document.title = mozL10n.get("standalone_title_with_status", @@ -690,7 +743,7 @@ ); @@ -770,6 +823,22 @@ }, /** + * Asks the user for the media privileges, handling the result appropriately. + */ + getMediaPrivs: function() { + this.setState({callStatus: "gumPrompt"}); + multiplexGum.getPermsAndCacheMedia({audio:true, video:true}, + function(localStream) { + this.props.conversation.gotMediaPrivs(); + }.bind(this), + function(errorCode) { + multiplexGum.reset(); + this.setState({callStatus: "failure"}); + }.bind(this) + ); + }, + + /** * Actually starts the call. */ startCall: function() { @@ -861,6 +930,8 @@ * Handles ending a call by resetting the view to the start state. */ _endCall: function() { + multiplexGum.reset(); + if (this.state.callStatus !== "failure") { this.setState({callStatus: "end"}); } @@ -887,14 +958,14 @@ notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackApiClient: React.PropTypes.object.isRequired, // XXX New types for flux style standaloneAppStore: React.PropTypes.instanceOf( loop.store.StandaloneAppStore).isRequired, activeRoomStore: React.PropTypes.instanceOf( loop.store.ActiveRoomStore).isRequired, - dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, + feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) }, getInitialState: function() { @@ -931,7 +1002,7 @@ helper={this.props.helper} notifications={this.props.notifications} sdk={this.props.sdk} - feedbackApiClient={this.props.feedbackApiClient} + feedbackStore={this.props.feedbackStore} /> ); } @@ -992,18 +1063,27 @@ dispatcher: dispatcher, sdk: OT }); + var feedbackClient = new loop.FeedbackAPIClient( + loop.config.feedbackApiUrl, { + product: loop.config.feedbackProductName, + user_agent: navigator.userAgent, + url: document.location.origin + }); + // Stores var standaloneAppStore = new loop.store.StandaloneAppStore({ conversation: conversation, dispatcher: dispatcher, helper: helper, sdk: OT }); - var activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: standaloneMozLoop, sdkDriver: sdkDriver }); + var feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: feedbackClient + }); window.addEventListener("unload", function() { dispatcher.dispatch(new sharedActions.WindowUnload()); @@ -1015,7 +1095,7 @@ helper={helper} notifications={notifications} sdk={OT} - feedbackApiClient={feedbackApiClient} + feedbackStore={feedbackStore} standaloneAppStore={standaloneAppStore} activeRoomStore={activeRoomStore} dispatcher={dispatcher} @@ -1036,6 +1116,8 @@ return { CallUrlExpiredView: CallUrlExpiredView, PendingConversationView: PendingConversationView, + GumPromptConversationView: GumPromptConversationView, + WaitingConversationView: WaitingConversationView, StartConversationView: StartConversationView, FailedConversationView: FailedConversationView, OutgoingConversationView: OutgoingConversationView, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties 2014-11-26 21:45:48.000000000 +0000 @@ -0,0 +1,129 @@ +## LOCALIZATION NOTE: In this file, don't translate the part between {{..}} +restart_call=Rejoin +conversation_has_ended=Your conversation has ended. +call_timeout_notification_text=Your call did not go through. +missing_conversation_info=Missing conversation information. +network_disconnected=The network connection terminated abruptly. +peer_ended_conversation2=The person you were calling has ended the conversation. +call_failed_title=Call failed. +generic_failure_title=Something went wrong. +generic_failure_with_reason2=You can try again or email a link to be reached at later. +generic_failure_no_reason2=Would you like to try again? +retry_call_button=Retry +unable_retrieve_call_info=Unable to retrieve conversation information. +hangup_button_title=Hang up +hangup_button_caption2=Exit +mute_local_audio_button_title=Mute your audio +unmute_local_audio_button_title=Unmute your audio +mute_local_video_button_title=Mute your video +unmute_local_video_button_title=Unmute your video +outgoing_call_title=Start conversation? +call_with_contact_title=Conversation with {{incomingCallIdentity}} +welcome=Welcome to the {{clientShortname}} web client. +incompatible_browser=Incompatible Browser +powered_by_webrtc=The audio and video components of {{clientShortname}} are powered by WebRTC. +use_latest_firefox=Please try this link in a WebRTC-enabled browser, such as {{firefoxBrandNameLink}}. +incompatible_device=Incompatible device +sorry_device_unsupported=Sorry, {{clientShortname}} does not currently support your device. +use_firefox_windows_mac_linux=Please open this page using the latest {{brandShortname}} on Windows, Android, Mac or Linux. +connection_error_see_console_notification=Call failed; see console for details. +call_url_unavailable_notification_heading=Oops! +call_url_unavailable_notification_message2=Sorry, this URL is not available. It may be expired or entered incorrectly. +promote_firefox_hello_heading=Download {{brandShortname}} to make free audio and video calls! +get_firefox_button=Get {{brandShortname}} +initiate_call_button_label2=Ready to start your conversation? +initiate_audio_video_call_button2=Start +initiate_audio_video_call_tooltip2=Start a video conversation +initiate_audio_call_button2=Voice conversation +initiate_call_cancel_button=Cancel +legal_text_and_links=By using {{clientShortname}} you agree to the {{terms_of_use_url}} and {{privacy_notice_url}} +terms_of_use_link_text=Terms of use +privacy_notice_link_text=Privacy notice +invite_header_text=Invite someone to join you. + +## LOCALIZATION NOTE(brandShortname): This should not be localized and +## should remain "Firefox" for all locales. +brandShortname=Firefox +## LOCALIZATION NOTE(clientShortname2): This should not be localized and +## should remain "Firefox Hello" for all locales. +clientShortname2=Firefox Hello +## LOCALIZATION NOTE(vendorShortname): This should not be localized and +## should remain "Mozilla" for all locales. +vendorShortname=Mozilla + +## LOCALIZATION NOTE(client_alttext): {{clientShortname}} will be replaced with the +## value of the clientShortname2 string above. +client_alttext={{clientShortname}} logo +vendor_alttext={{vendorShortname}} logo + +## LOCALIZATION NOTE (call_url_creation_date_label): Example output: (from May 26, 2014) +call_url_creation_date_label=(from {{call_url_creation_date}}) +call_progress_getting_media_description={{clientShortname}} requires access to your camera and microphone. +call_progress_getting_media_title=Waiting for media… +call_progress_connecting_description=Connecting… +call_progress_ringing_description=Ringing… +fxos_app_needed=Please install the {{fxosAppName}} app from the Firefox Marketplace. + +feedback_call_experience_heading2=How was your conversation? +feedback_what_makes_you_sad=What makes you sad? +feedback_thank_you_heading=Thank you for your feedback! +feedback_category_audio_quality=Audio quality +feedback_category_video_quality=Video quality +feedback_category_was_disconnected=Was disconnected +feedback_category_confusing=Confusing +feedback_category_other=Other: +feedback_custom_category_text_placeholder=What went wrong? +feedback_submit_button=Submit +feedback_back_button=Back +## LOCALIZATION NOTE (feedback_window_will_close_in2): +## Gaia l10n format; see https://github.com/mozilla-b2g/gaia/blob/f108c706fae43cd61628babdd9463e7695b2496e/apps/email/locales/email.en-US.properties#L387 +## In this item, don't translate the part between {{..}} +feedback_window_will_close_in2={[ plural(countdown) ]} +feedback_window_will_close_in2[one] = This window will close in {{countdown}} second +feedback_window_will_close_in2[two] = This window will close in {{countdown}} seconds +feedback_window_will_close_in2[few] = This window will close in {{countdown}} seconds +feedback_window_will_close_in2[many] = This window will close in {{countdown}} seconds +feedback_window_will_close_in2[other] = This window will close in {{countdown}} seconds + +## LOCALIZATION_NOTE (feedback_rejoin_button): Displayed on the feedback form after +## a signed-in to signed-in user call. +## https://people.mozilla.org/~dhenein/labs/loop-mvp-spec/#feedback +feedback_rejoin_button=Rejoin +## LOCALIZATION NOTE (feedback_report_user_button): Used to report a user in the case of +## an abusive user. +feedback_report_user_button=Report User + +## LOCALIZATION_NOTE(first_time_experience.title): clientShortname will be +## replaced by the brand name +first_time_experience_title={{clientShortname}} — Join the conversation +first_time_experience_button_label=Get Started + +help_label=Help +tour_label=Tour + +rooms_default_room_name_template=Conversation {{conversationLabel}} +rooms_leave_button_label=Leave +rooms_list_copy_url_tooltip=Copy Link +rooms_list_delete_tooltip=Delete conversation +rooms_list_deleteConfirmation_label=Are you sure? +rooms_name_this_room_label=Name this conversation +rooms_new_room_button_label=Start a conversation +rooms_only_occupant_label=You're the first one here. +rooms_panel_title=Choose a conversation or start a new one +rooms_room_full_label=There are already two people in this conversation. +rooms_room_full_call_to_action_nonFx_label=Download {{brandShortname}} to start your own +rooms_room_full_call_to_action_label=Learn more about {{clientShortname}} » +rooms_room_joined_label=Someone has joined the conversation! +rooms_room_join_label=Join the conversation +rooms_display_name_guest=Guest +rooms_unavailable_notification_message=Sorry, you cannot join this conversation. The link may be expired or invalid. +rooms_media_denied_message=We could not get access to your microphone or camera. Please reload the page to try again. + +## LOCALIZATION_NOTE(standalone_title_with_status): {{clientShortname}} will be +## replaced by the brand name and {{currentStatus}} will be replaced +## by the current call status (Connecting, Ringing, etc.) +standalone_title_with_status={{clientShortname}} — {{currentStatus}} +status_in_conversation=In conversation +status_conversation_ended=Conversation ended +status_error=Something went wrong +support_link=Get Help diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/l10n/loop.en-US.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/l10n/loop.en-US.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/content/l10n/loop.en-US.properties 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/content/l10n/loop.en-US.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ -## LOCALIZATION NOTE: In this file, don't translate the part between {{..}} -restart_call=Rejoin -conversation_has_ended=Your conversation has ended. -call_timeout_notification_text=Your call did not go through. -missing_conversation_info=Missing conversation information. -network_disconnected=The network connection terminated abruptly. -peer_ended_conversation2=The person you were calling has ended the conversation. -call_failed_title=Call failed. -connection_error_see_console_notification=Call failed; see console for details. -generic_failure_title=Something went wrong. -generic_failure_with_reason2=You can try again or email a link to be reached at later. -generic_failure_no_reason2=Would you like to try again? -retry_call_button=Retry -feedback_report_user_button=Report User -unable_retrieve_call_info=Unable to retrieve conversation information. -hangup_button_title=Hang up -hangup_button_caption2=Exit -mute_local_audio_button_title=Mute your audio -unmute_local_audio_button_title=Unmute your audio -mute_local_video_button_title=Mute your video -unmute_local_video_button_title=Unmute your video -outgoing_call_title=Start conversation? -call_with_contact_title=Conversation with {{incomingCallIdentity}} -welcome=Welcome to the {{clientShortname}} web client. -incompatible_browser=Incompatible Browser -powered_by_webrtc=The audio and video components of {{clientShortname}} are powered by WebRTC. -use_latest_firefox=Please try this link in a WebRTC-enabled browser, such as {{firefoxBrandNameLink}}. -incompatible_device=Incompatible device -sorry_device_unsupported=Sorry, {{clientShortname}} does not currently support your device. -use_firefox_windows_mac_linux=Please open this page using the latest {{brandShortname}} on Windows, Android, Mac or Linux. -connection_error_see_console_notification=Call failed; see console for details. -call_url_unavailable_notification_heading=Oops! -call_url_unavailable_notification_message2=Sorry, this URL is not available. It may be expired or entered incorrectly. -promote_firefox_hello_heading=Download {{brandShortname}} to make free audio and video calls! -get_firefox_button=Get {{brandShortname}} -initiate_call_button_label2=Ready to start your conversation? -initiate_audio_video_call_button2=Start -initiate_audio_video_call_tooltip2=Start a video conversation -initiate_audio_call_button2=Voice conversation -initiate_call_cancel_button=Cancel -legal_text_and_links=By using {{clientShortname}} you agree to the {{terms_of_use_url}} and {{privacy_notice_url}} -terms_of_use_link_text=Terms of use -privacy_notice_link_text=Privacy notice -invite_header_text=Invite someone to join you. - -## LOCALIZATION NOTE(brandShortname): This should not be localized and -## should remain "Firefox" for all locales. -brandShortname=Firefox -## LOCALIZATION NOTE(clientShortname2): This should not be localized and -## should remain "Firefox Hello" for all locales. -clientShortname2=Firefox Hello -## LOCALIZATION NOTE(vendorShortname): This should not be localized and -## should remain "Mozilla" for all locales. -vendorShortname=Mozilla - -## LOCALIZATION NOTE(client_alttext): {{clientShortname}} will be replaced with the -## value of the clientShortname2 string above. -client_alttext={{clientShortname}} logo -vendor_alttext={{vendorShortname}} logo - -## LOCALIZATION NOTE (call_url_creation_date_label): Example output: (from May 26, 2014) -call_url_creation_date_label=(from {{call_url_creation_date}}) -call_progress_connecting_description=Connecting… -call_progress_ringing_description=Ringing… -fxos_app_needed=Please install the {{fxosAppName}} app from the Firefox Marketplace. - -feedback_call_experience_heading2=How was your conversation? -feedback_what_makes_you_sad=What makes you sad? -feedback_thank_you_heading=Thank you for your feedback! -feedback_category_audio_quality=Audio quality -feedback_category_video_quality=Video quality -feedback_category_was_disconnected=Was disconnected -feedback_category_confusing=Confusing -feedback_category_other=Other: -feedback_custom_category_text_placeholder=What went wrong? -feedback_submit_button=Submit -feedback_back_button=Back -## LOCALIZATION NOTE (feedback_window_will_close_in2): -## Gaia l10n format; see https://github.com/mozilla-b2g/gaia/blob/f108c706fae43cd61628babdd9463e7695b2496e/apps/email/locales/email.en-US.properties#L387 -## In this item, don't translate the part between {{..}} -feedback_window_will_close_in2={[ plural(countdown) ]} -feedback_window_will_close_in2[one] = This window will close in {{countdown}} second -feedback_window_will_close_in2[two] = This window will close in {{countdown}} seconds -feedback_window_will_close_in2[few] = This window will close in {{countdown}} seconds -feedback_window_will_close_in2[many] = This window will close in {{countdown}} seconds -feedback_window_will_close_in2[other] = This window will close in {{countdown}} seconds - -## LOCALIZATION_NOTE (feedback_rejoin_button): Displayed on the feedback form after -## a signed-in to signed-in user call. -## https://people.mozilla.org/~dhenein/labs/loop-mvp-spec/#feedback -feedback_rejoin_button=Rejoin -## LOCALIZATION NOTE (feedback_report_user_button): Used to report a user in the case of -## an abusive user. -feedback_report_user_button=Report User - -## LOCALIZATION_NOTE(first_time_experience.title): clientShortname will be -## replaced by the brand name -first_time_experience_title={{clientShortname}} — Join the conversation -first_time_experience_button_label=Get Started - -help_label=Help -tour_label=Tour - -rooms_default_room_name_template=Conversation {{conversationLabel}} -rooms_leave_button_label=Leave -rooms_list_copy_url_tooltip=Copy Link -rooms_list_delete_tooltip=Delete conversation -rooms_list_deleteConfirmation_label=Are you sure? -rooms_name_this_room_label=Name this conversation -rooms_new_room_button_label=Start a conversation -rooms_only_occupant_label=You're the first one here. -rooms_panel_title=Choose a conversation or start a new one -rooms_room_full_label=There are already two people in this conversation. -rooms_room_full_call_to_action_nonFx_label=Download {{brandShortname}} to start your own -rooms_room_full_call_to_action_label=Learn more about {{clientShortname}} » -rooms_room_joined_label=Someone has joined the conversation! -rooms_room_join_label=Join the conversation -rooms_display_name_guest=Guest - -## LOCALIZATION_NOTE(standalone_title_with_status): {{clientShortname}} will be -## replaced by the brand name and {{currentStatus}} will be replaced -## by the current call status (Connecting, Ringing, etc.) -standalone_title_with_status={{clientShortname}} — {{currentStatus}} -status_in_conversation=In conversation -status_conversation_ended=Conversation ended -status_error=Something went wrong - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/Makefile thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/Makefile --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/Makefile 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/Makefile 2014-11-26 21:45:48.000000000 +0000 @@ -12,7 +12,7 @@ # Bug 1066176 tracks moving all functionality currently here # to the Gruntfile and getting rid of this Makefile entirely. -LOOP_SERVER_URL := $(shell echo $${LOOP_SERVER_URL-http://localhost:5000}) +LOOP_SERVER_URL := $(shell echo $${LOOP_SERVER_URL-http://localhost:5000/v0}) LOOP_FEEDBACK_API_URL := $(shell echo $${LOOP_FEEDBACK_API_URL-"https://input.allizom.org/api/v1/feedback"}) LOOP_FEEDBACK_PRODUCT_NAME := $(shell echo $${LOOP_FEEDBACK_PRODUCT_NAME-Loop}) LOOP_BRAND_WEBSITE_URL := $(shell echo $${LOOP_BRAND_WEBSITE_URL-"https://www.mozilla.org/firefox/"}) @@ -84,3 +84,5 @@ @echo "loop.config.fxosApp = loop.config.fxosApp || {};" >> content/config.js @echo "loop.config.fxosApp.name = 'Loop';" >> content/config.js @echo "loop.config.fxosApp.manifestUrl = 'http://fake-market.herokuapp.com/apps/packagedApp/manifest.webapp';" >> content/config.js + @echo "loop.config.roomsSupportUrl = 'https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc';" >> content/config.js + @echo "loop.config.guestSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" >> content/config.js diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/server.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/server.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/standalone/server.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/standalone/server.js 2014-11-26 21:45:48.000000000 +0000 @@ -18,7 +18,7 @@ res.send([ "var loop = loop || {};", "loop.config = loop.config || {};", - "loop.config.serverUrl = 'http://localhost:" + loopServerPort + "';", + "loop.config.serverUrl = 'http://localhost:" + loopServerPort + "/v0';", "loop.config.feedbackApiUrl = '" + feedbackApiUrl + "';", "loop.config.feedbackProductName = '" + feedbackProductName + "';", // XXX Update with the real marketplace url once the FxOS Loop app is @@ -30,7 +30,9 @@ "loop.config.legalWebsiteUrl = '/legal/terms';", "loop.config.fxosApp = loop.config.fxosApp || {};", "loop.config.fxosApp.name = 'Loop';", - "loop.config.fxosApp.manifestUrl = 'http://fake-market.herokuapp.com/apps/packagedApp/manifest.webapp';" + "loop.config.fxosApp.manifestUrl = 'http://fake-market.herokuapp.com/apps/packagedApp/manifest.webapp';", + "loop.config.roomsSupportUrl = 'https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc';", + "loop.config.guestSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" ].join("\n")); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/client_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/client_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/client_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/client_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -28,11 +28,10 @@ callback = sinon.spy(); fakeToken = "fakeTokenText"; mozLoop = { - getLoopCharPref: sandbox.stub() + getLoopPref: sandbox.stub() .returns(null) .withArgs("hawk-session-token") .returns(fakeToken), - ensureRegistered: sinon.stub().callsArgWith(1, null), noteCallUrlExpiry: sinon.spy(), hawkRequest: sinon.stub(), LOOP_SESSION_TYPE: { @@ -55,21 +54,6 @@ describe("loop.Client", function() { describe("#deleteCallUrl", function() { - it("should ensure loop is registered", function() { - client.deleteCallUrl("fakeToken", mozLoop.LOOP_SESSION_TYPE.FXA, callback); - - sinon.assert.calledOnce(mozLoop.ensureRegistered); - }); - - it("should send an error when registration fails", function() { - mozLoop.ensureRegistered.callsArgWith(1, "offline"); - - client.deleteCallUrl("fakeToken", mozLoop.LOOP_SESSION_TYPE.FXA, callback); - - sinon.assert.calledOnce(callback); - sinon.assert.calledWithExactly(callback, "offline"); - }); - it("should make a delete call to /call-url/{fakeToken}", function() { client.deleteCallUrl(fakeToken, mozLoop.LOOP_SESSION_TYPE.GUEST, callback); @@ -106,21 +90,6 @@ }); describe("#requestCallUrl", function() { - it("should ensure loop is registered", function() { - client.requestCallUrl("foo", callback); - - sinon.assert.calledOnce(mozLoop.ensureRegistered); - }); - - it("should send an error when registration fails", function() { - mozLoop.ensureRegistered.callsArgWith(1, "offline"); - - client.requestCallUrl("foo", callback); - - sinon.assert.calledOnce(callback); - sinon.assert.calledWithExactly(callback, "offline"); - }); - it("should post to /call-url/", function() { client.requestCallUrl("foo", callback); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/contacts_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/contacts_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/contacts_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/contacts_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -75,6 +75,80 @@ expect(addButton).to.not.equal(null); expect(addButton.textContent).to.eql(fakeAddContactButtonText); }); + it("should have all fields required by default", function() { + var view = TestUtils.renderIntoDocument( + loop.contacts.ContactDetailsForm({mode: "add"})); + var nameInput = view.getDOMNode().querySelector("input[type='text']"); + var telInput = view.getDOMNode().querySelector("input[type='tel']"); + var emailInput = view.getDOMNode().querySelector("input[type='email']"); + + expect(nameInput.required).to.equal(true); + expect(emailInput.required).to.equal(true); + expect(telInput.required).to.equal(true); + }); + it("should have email and tel required after a name is input", function() { + var view = TestUtils.renderIntoDocument( + loop.contacts.ContactDetailsForm({mode: "add"})); + var nameInput = view.getDOMNode().querySelector("input[type='text']"); + TestUtils.Simulate.change(nameInput, {target: {value: "Jenny"}}); + var telInput = view.getDOMNode().querySelector("input[type='tel']"); + var emailInput = view.getDOMNode().querySelector("input[type='email']"); + + expect(nameInput.required).to.equal(true); + expect(emailInput.required).to.equal(true); + expect(telInput.required).to.equal(true); + }); + it("should allow a contact with only a name and a phone number", function() { + var view = TestUtils.renderIntoDocument( + loop.contacts.ContactDetailsForm({mode: "add"})); + var nameInput = view.getDOMNode().querySelector("input[type='text']"); + TestUtils.Simulate.change(nameInput, {target: {value: "Jenny"}}); + var telInput = view.getDOMNode().querySelector("input[type='tel']"); + TestUtils.Simulate.change(telInput, {target: {value: "867-5309"}}); + var emailInput = view.getDOMNode().querySelector("input[type='email']"); + + expect(nameInput.checkValidity()).to.equal(true, "nameInput"); + expect(emailInput.required).to.equal(false, "emailInput"); + expect(telInput.checkValidity()).to.equal(true, "telInput"); + }); + it("should allow a contact with only a name and email", function() { + var view = TestUtils.renderIntoDocument( + loop.contacts.ContactDetailsForm({mode: "add"})); + var nameInput = view.getDOMNode().querySelector("input[type='text']"); + TestUtils.Simulate.change(nameInput, {target: {value: "Example"}}); + var emailInput = view.getDOMNode().querySelector("input[type='email']"); + TestUtils.Simulate.change(emailInput, {target: {value: "test@example.com"}}); + var telInput = view.getDOMNode().querySelector("input[type='tel']"); + + expect(nameInput.checkValidity()).to.equal(true); + expect(emailInput.checkValidity()).to.equal(true); + expect(telInput.required).to.equal(false); + }); + it("should not allow a contact with only a name", function() { + var view = TestUtils.renderIntoDocument( + loop.contacts.ContactDetailsForm({mode: "add"})); + var nameInput = view.getDOMNode().querySelector("input[type='text']"); + TestUtils.Simulate.change(nameInput, {target: {value: "Example"}}); + var emailInput = view.getDOMNode().querySelector("input[type='email']"); + var telInput = view.getDOMNode().querySelector("input[type='tel']"); + + expect(nameInput.checkValidity()).to.equal(true); + expect(emailInput.checkValidity()).to.equal(false); + expect(telInput.checkValidity()).to.equal(false); + }); + it("should not allow a contact without name", function() { + var view = TestUtils.renderIntoDocument( + loop.contacts.ContactDetailsForm({mode: "add"})); + var nameInput = view.getDOMNode().querySelector("input[type='text']"); + var emailInput = view.getDOMNode().querySelector("input[type='email']"); + TestUtils.Simulate.change(emailInput, {target: {value: "test@example.com"}}); + var telInput = view.getDOMNode().querySelector("input[type='tel']"); + TestUtils.Simulate.change(telInput, {target: {value: "867-5309"}}); + + expect(nameInput.checkValidity()).to.equal(false); + expect(emailInput.checkValidity()).to.equal(true); + expect(telInput.checkValidity()).to.equal(true); + }); }); describe("edit mode", function() { it("should render 'edit' header", function() { @@ -137,28 +211,21 @@ it("should not set the value on the object if the new value is empty," + " it didn't exist before, and it is optional", function() { var contact = {}; - loop.contacts._setPreferred(contact, {field: "fakeField", value: "", optional: true}); + loop.contacts._setPreferred(contact, "fakeField", ""); expect(contact).to.not.have.property("fakeField"); }); it("should clear the value on the object if the new value is empty," + " it existed before, and it is optional", function() { var contact = {fakeField: [{value: "foobar"}]}; - loop.contacts._setPreferred(contact, {field: "fakeField", value: "", optional: true}); + loop.contacts._setPreferred(contact, "fakeField", ""); expect(contact["fakeField"][0].value).to.eql(""); }); it("should set the value on the object if the new value is empty," + " and it did not exist before", function() { - var contact = {}; - loop.contacts._setPreferred(contact, {field: "fakeField", value: ""}); - - expect(contact).to.have.property("fakeField"); - }); - it("should set the value on the object if the new value is empty," + - " and it did not exist before", function() { var contact = {fakeField: [{value: "foobar"}]}; - loop.contacts._setPreferred(contact, {field: "fakeField", value: "barbaz"}); + loop.contacts._setPreferred(contact, "fakeField", "barbaz"); expect(contact["fakeField"][0].value).to.eql("barbaz"); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/conversation_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/conversation_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/conversation_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/conversation_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -38,9 +38,14 @@ get locale() { return "en-US"; }, - setLoopCharPref: sinon.stub(), - getLoopCharPref: sinon.stub().returns("http://fakeurl"), - getLoopBoolPref: sinon.stub(), + setLoopPref: sinon.stub(), + getLoopPref: function(prefName) { + if (prefName == "debug.sdk") { + return false; + } + + return "http://fake"; + }, calls: { clearCallInProgress: sinon.stub() }, @@ -169,9 +174,8 @@ dispatcher: dispatcher, sdkDriver: {} }); - roomStore = new loop.store.RoomStore({ + roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop, - dispatcher: dispatcher }); conversationAppStore = new loop.store.ConversationAppStore({ dispatcher: dispatcher, @@ -229,7 +233,8 @@ }); describe("IncomingConversationView", function() { - var conversationAppStore, conversation, client, icView, oldTitle; + var conversationAppStore, conversation, client, icView, oldTitle, + feedbackStore; function mountTestComponent() { return TestUtils.renderIntoDocument( @@ -237,7 +242,8 @@ client: client, conversation: conversation, sdk: {}, - conversationAppStore: conversationAppStore + conversationAppStore: conversationAppStore, + feedbackStore: feedbackStore })); } @@ -253,6 +259,9 @@ dispatcher: dispatcher, mozLoop: navigator.mozLoop }); + feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }); sandbox.stub(conversation, "setOutgoingSessionData"); }); @@ -547,7 +556,7 @@ }); describe("#blocked", function() { - var mozLoop; + var mozLoop, deleteCallUrlStub; beforeEach(function() { icView = mountTestComponent(); @@ -564,6 +573,9 @@ FXA: 2 } }; + + deleteCallUrlStub = sandbox.stub(loop.Client.prototype, + "deleteCallUrl"); }); it("should call mozLoop.stopAlerting", function() { @@ -578,12 +590,10 @@ .withArgs("sessionType") .returns(mozLoop.LOOP_SESSION_TYPE.FXA); - var deleteCallUrl = sandbox.stub(loop.Client.prototype, - "deleteCallUrl"); icView.declineAndBlock(); - sinon.assert.calledOnce(deleteCallUrl); - sinon.assert.calledWithExactly(deleteCallUrl, + sinon.assert.calledOnce(deleteCallUrlStub); + sinon.assert.calledWithExactly(deleteCallUrlStub, "fakeToken", mozLoop.LOOP_SESSION_TYPE.FXA, sinon.match.func); }); @@ -602,9 +612,7 @@ var fakeError = { error: true }; - sandbox.stub(loop.Client.prototype, "deleteCallUrl", function(_, __, cb) { - cb(fakeError); - }); + deleteCallUrlStub.callsArgWith(2, fakeError); icView.declineAndBlock(); sinon.assert.calledOnce(log); @@ -647,7 +655,6 @@ icView = mountTestComponent(); conversation.set("loopToken", "fakeToken"); - navigator.mozLoop.getLoopCharPref.returns("http://fake"); stubComponent(sharedView, "ConversationView"); }); @@ -917,6 +924,7 @@ pause: sinon.spy(), removeAttribute: sinon.spy() }; + navigator.mozLoop.doNotDisturb = false; sandbox.stub(window, "Audio").returns(fakeAudio); view = TestUtils.renderIntoDocument( diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/conversationViews_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/conversationViews_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/conversationViews_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/conversationViews_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -44,7 +44,7 @@ }; navigator.mozLoop = { - getLoopCharPref: sinon.stub().returns("http://fakeurl"), + getLoopPref: sinon.stub().returns("http://fakeurl"), composeEmail: sinon.spy(), get appVersionInfo() { return { @@ -445,13 +445,14 @@ }); describe("OutgoingConversationView", function() { - var store; + var store, feedbackStore; function mountTestComponent() { return TestUtils.renderIntoDocument( loop.conversationViews.OutgoingConversationView({ dispatcher: dispatcher, - store: store + store: store, + feedbackStore: feedbackStore })); } @@ -461,6 +462,9 @@ client: {}, sdkDriver: {} }); + feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }); }); it("should render the CallFailedView when the call state is 'terminated'", @@ -506,6 +510,22 @@ loop.shared.views.FeedbackView); }); + it("should play the terminated sound when the call state is 'finished'", + function() { + var fakeAudio = { + play: sinon.spy(), + pause: sinon.spy(), + removeAttribute: sinon.spy() + }; + sandbox.stub(window, "Audio").returns(fakeAudio); + + store.set({callState: CALL_STATES.FINISHED}); + + view = mountTestComponent(); + + sinon.assert.calledOnce(fakeAudio.play); + }); + it("should update the rendered views when the state is changed.", function() { store.set({ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/index.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/index.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/index.html 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/index.html 2014-11-26 21:45:48.000000000 +0000 @@ -43,8 +43,11 @@ + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/panel_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/panel_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/panel_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/panel_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -34,9 +34,8 @@ get locale() { return "en-US"; }, - getLoopBoolPref: sandbox.stub(), - setLoopCharPref: sandbox.stub(), - getLoopCharPref: sandbox.stub().returns("unseen"), + setLoopPref: sandbox.stub(), + getLoopPref: sandbox.stub().returns("unseen"), getPluralForm: function() { return "fakeText"; }, @@ -155,8 +154,7 @@ }; dispatcher = new loop.Dispatcher(); - roomStore = new loop.store.RoomStore({ - dispatcher: dispatcher, + roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop }); }); @@ -176,15 +174,16 @@ describe("loop.rooms.enabled on", function() { beforeEach(function() { - navigator.mozLoop.getLoopBoolPref = function(pref) { - if (pref === "rooms.enabled") { + navigator.mozLoop.getLoopPref = function(pref) { + if (pref === "rooms.enabled" || + pref === "gettingStarted.seen") { return true; } }; view = createTestPanelView(); - [callTab, roomsTab, contactsTab] = + [roomsTab, contactsTab] = TestUtils.scryRenderedDOMComponentsWithClass(view, "tab"); }); @@ -203,21 +202,15 @@ expect(roomsTab.getDOMNode().classList.contains("selected")) .to.be.true; }); - - it("should select call tab when clicking tab button", function() { - TestUtils.Simulate.click( - view.getDOMNode().querySelector("li[data-tab-name=\"call\"]")); - - expect(callTab.getDOMNode().classList.contains("selected")) - .to.be.true; - }); }); describe("loop.rooms.enabled off", function() { beforeEach(function() { - navigator.mozLoop.getLoopBoolPref = function(pref) { + navigator.mozLoop.getLoopPref = function(pref) { if (pref === "rooms.enabled") { return false; + } else if (pref === "gettingStarted.seen") { + return true; } }; @@ -363,12 +356,71 @@ }); }); + describe("Help", function() { + var supportUrl = "https://example.com"; + + beforeEach(function() { + navigator.mozLoop.getLoopPref = function(pref) { + if (pref === "support_url") + return supportUrl; + return "unseen"; + }; + + sandbox.stub(window, "open"); + sandbox.stub(window, "close"); + }); + + it("should open a tab to the support page", function() { + var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown()); + + TestUtils.Simulate + .click(view.getDOMNode().querySelector(".icon-help")); + + sinon.assert.calledOnce(window.open); + sinon.assert.calledWithExactly(window.open, supportUrl); + }); + }); + describe("#render", function() { it("should render a ToSView", function() { var view = createTestPanelView(); TestUtils.findRenderedComponentWithType(view, loop.panel.ToSView); }); + + it("should not render a ToSView when the view has been 'seen'", function() { + navigator.mozLoop.getLoopPref = function() { + return "seen"; + }; + var view = createTestPanelView(); + + try { + TestUtils.findRenderedComponentWithType(view, loop.panel.ToSView); + sinon.assert.fail("Should not find the ToSView if it has been 'seen'"); + } catch (ex) {} + }); + + it("should render a GettingStarted view", function() { + navigator.mozLoop.getLoopPref = function(pref) { + return false; + }; + var view = createTestPanelView(); + + TestUtils.findRenderedComponentWithType(view, loop.panel.GettingStartedView); + }); + + it("should not render a GettingStartedView when the view has been seen", function() { + navigator.mozLoop.getLoopPref = function() { + return true; + }; + var view = createTestPanelView(); + + try { + TestUtils.findRenderedComponentWithType(view, loop.panel.GettingStartedView); + sinon.assert.fail("Should not find the GettingStartedView if it has been seen"); + } catch (ex) {} + }); + }); }); @@ -764,8 +816,7 @@ beforeEach(function() { fakeEmail = "fakeEmail@example.com"; dispatcher = new loop.Dispatcher(); - roomStore = new loop.store.RoomStore({ - dispatcher: dispatcher, + roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop }); roomStore.setStoreState({ @@ -841,7 +892,7 @@ it("should not render when the value of loop.seenToS is set to 'seen'", function(done) { - navigator.mozLoop.getLoopCharPref = function() { + navigator.mozLoop.getLoopPref = function() { return "seen"; }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/roomViews_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/roomViews_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/desktop-local/roomViews_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/desktop-local/roomViews_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -30,13 +30,11 @@ return x; }); - activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: {}, sdkDriver: {} }); - roomStore = new loop.store.RoomStore({ - dispatcher: dispatcher, + roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: {}, activeRoomStore: activeRoomStore }); @@ -65,6 +63,7 @@ roomState: ROOM_STATES.INIT, audioMuted: false, videoMuted: false, + failureReason: undefined, foo: "bar" }); }); @@ -118,6 +117,48 @@ new sharedActions.EmailRoomUrl({roomUrl: "http://invalid"})); }); + describe("Rename Room", function() { + var roomNameBox; + + beforeEach(function() { + view = mountTestComponent(); + view.setState({ + roomToken: "fakeToken", + roomName: "fakeName" + }); + + roomNameBox = view.getDOMNode().querySelector('.input-room-name'); + + React.addons.TestUtils.Simulate.change(roomNameBox, { target: { + value: "reallyFake" + }}); + }); + + it("should dispatch a RenameRoom action when the focus is lost", + function() { + React.addons.TestUtils.Simulate.blur(roomNameBox); + + sinon.assert.calledOnce(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.RenameRoom({ + roomToken: "fakeToken", + newRoomName: "reallyFake" + })); + }); + + it("should dispatch a RenameRoom action when enter is pressed", + function() { + React.addons.TestUtils.Simulate.submit(roomNameBox); + + sinon.assert.calledOnce(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.RenameRoom({ + roomToken: "fakeToken", + newRoomName: "reallyFake" + })); + }); + }); + describe("Copy Button", function() { beforeEach(function() { view = mountTestComponent(); @@ -158,7 +199,10 @@ return TestUtils.renderIntoDocument( new loop.roomViews.DesktopRoomConversationView({ dispatcher: dispatcher, - roomStore: roomStore + roomStore: roomStore, + feedbackStore: new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }) })); } @@ -275,6 +319,16 @@ TestUtils.findRenderedComponentWithType(view, loop.roomViews.DesktopRoomConversationView); }); + + it("should render the FeedbackView if roomState is `ENDED`", + function() { + activeRoomStore.setStoreState({roomState: ROOM_STATES.ENDED}); + + view = mountTestComponent(); + + TestUtils.findRenderedComponentWithType(view, + loop.shared.views.FeedbackView); + }); }); }); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/browser_fxa_login.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/browser_fxa_login.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/browser_fxa_login.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/browser_fxa_login.js 2014-11-26 21:45:48.000000000 +0000 @@ -40,6 +40,7 @@ add_task(function* setup() { Services.prefs.setCharPref("loop.server", BASE_URL); Services.prefs.setCharPref("services.push.serverURL", "ws://localhost/"); + Services.prefs.setBoolPref("loop.gettingStarted.seen", true); MozLoopServiceInternal.mocks.pushHandler = mockPushHandler; // Normally the same pushUrl would be registered but we change it in the test // to be able to check for success on the second registration. @@ -51,6 +52,7 @@ yield promiseDeletedOAuthParams(BASE_URL); Services.prefs.clearUserPref("loop.server"); Services.prefs.clearUserPref("services.push.serverURL"); + Services.prefs.clearUserPref("loop.gettingStarted.seen"); MozLoopServiceInternal.mocks.pushHandler = undefined; delete mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA]; delete mockPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA]; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js 2014-11-26 21:45:48.000000000 +0000 @@ -17,13 +17,13 @@ Assert.ok(gMozLoopAPI, "mozLoop should exist"); - // Test setLoopCharPref - gMozLoopAPI.setLoopCharPref("test", "foo"); + // Test setLoopPref + gMozLoopAPI.setLoopPref("test", "foo", Ci.nsIPrefBranch.PREF_STRING); Assert.equal(Services.prefs.getCharPref("loop.test"), "foo", "should set loop pref value correctly"); - // Test getLoopCharPref - Assert.equal(gMozLoopAPI.getLoopCharPref("test"), "foo", + // Test getLoopPref + Assert.equal(gMozLoopAPI.getLoopPref("test"), "foo", "should get loop pref value correctly"); }); @@ -36,7 +36,7 @@ Services.prefs.setBoolPref("loop.testBool", true); - // Test getLoopCharPref - Assert.equal(gMozLoopAPI.getLoopBoolPref("testBool"), true, + // Test getLoopPref + Assert.equal(gMozLoopAPI.getLoopPref("testBool"), true, "should get loop pref value correctly"); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/browser_toolbarbutton.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/browser_toolbarbutton.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/browser_toolbarbutton.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/browser_toolbarbutton.js 2014-11-26 21:45:48.000000000 +0000 @@ -8,11 +8,14 @@ "use strict"; Components.utils.import("resource://gre/modules/Promise.jsm", this); +const {LoopRoomsInternal} = Components.utils.import("resource:///modules/loop/LoopRooms.jsm", {}); +Services.prefs.setBoolPref("loop.gettingStarted.seen", true); registerCleanupFunction(function*() { MozLoopService.doNotDisturb = false; MozLoopServiceInternal.fxAOAuthProfile = null; yield MozLoopServiceInternal.clearError("testing"); + Services.prefs.clearUserPref("loop.gettingStarted.seen"); }); add_task(function* test_doNotDisturb() { @@ -79,3 +82,14 @@ Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state"); }); +add_task(function* test_room_participants() { + Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state"); + LoopRoomsInternal.rooms.set("test_room", {participants: [{displayName: "hugh", id: "008"}]}); + MozLoopServiceInternal.notifyStatusChanged(); + Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state"); + LoopRoomsInternal.rooms.set("test_room", {participants: []}); + MozLoopServiceInternal.notifyStatusChanged(); + Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state"); + LoopRoomsInternal.rooms.delete("test_room"); +}); + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/head.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/head.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/mochitest/head.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/mochitest/head.js 2014-11-26 21:45:48.000000000 +0000 @@ -183,7 +183,7 @@ } function getLoopString(stringID) { - return MozLoopServiceInternal.localizedStrings[stringID].textContent; + return MozLoopServiceInternal.localizedStrings.get(stringID); } /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/activeRoomStore_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/activeRoomStore_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/activeRoomStore_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/activeRoomStore_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -6,7 +6,9 @@ describe("loop.store.ActiveRoomStore", function () { "use strict"; + var SERVER_CODES = loop.store.SERVER_CODES; var ROOM_STATES = loop.store.ROOM_STATES; + var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS; var sandbox, dispatcher, store, fakeMozLoop, fakeSdkDriver; var fakeMultiplexGum; @@ -18,11 +20,14 @@ sandbox.stub(dispatcher, "dispatch"); fakeMozLoop = { + setLoopPref: sandbox.stub(), rooms: { - get: sandbox.stub(), - join: sandbox.stub(), - refreshMembership: sandbox.stub(), - leave: sandbox.stub() + get: sinon.stub(), + join: sinon.stub(), + refreshMembership: sinon.stub(), + leave: sinon.stub(), + on: sinon.stub(), + off: sinon.stub() } }; @@ -39,8 +44,7 @@ multiplexGum: fakeMultiplexGum }; - store = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + store = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: fakeMozLoop, sdkDriver: fakeSdkDriver }); @@ -51,21 +55,15 @@ }); describe("#constructor", function() { - it("should throw an error if the dispatcher is missing", function() { - expect(function() { - new loop.store.ActiveRoomStore({mozLoop: {}}); - }).to.Throw(/dispatcher/); - }); - it("should throw an error if mozLoop is missing", function() { expect(function() { - new loop.store.ActiveRoomStore({dispatcher: dispatcher}); + new loop.store.ActiveRoomStore(dispatcher); }).to.Throw(/mozLoop/); }); it("should throw an error if sdkDriver is missing", function() { expect(function() { - new loop.store.ActiveRoomStore({dispatcher: dispatcher, mozLoop: {}}); + new loop.store.ActiveRoomStore(dispatcher, {mozLoop: {}}); }).to.Throw(/sdkDriver/); }); }); @@ -91,8 +89,8 @@ sinon.match(ROOM_STATES.READY), fakeError); }); - it("should set the state to `FULL` on server errno 202", function() { - fakeError.errno = 202; + it("should set the state to `FULL` on server error room full", function() { + fakeError.errno = SERVER_CODES.ROOM_FULL; store.roomFailure({error: fakeError}); @@ -103,7 +101,28 @@ store.roomFailure({error: fakeError}); expect(store._storeState.roomState).eql(ROOM_STATES.FAILED); + expect(store._storeState.failureReason).eql(FAILURE_REASONS.UNKNOWN); }); + + it("should set the failureReason to EXPIRED_OR_INVALID on server error: " + + "invalid token", function() { + fakeError.errno = SERVER_CODES.INVALID_TOKEN; + + store.roomFailure({error: fakeError}); + + expect(store._storeState.roomState).eql(ROOM_STATES.FAILED); + expect(store._storeState.failureReason).eql(FAILURE_REASONS.EXPIRED_OR_INVALID); + }); + + it("should set the failureReason to EXPIRED_OR_INVALID on server error: " + + "expired", function() { + fakeError.errno = SERVER_CODES.EXPIRED; + + store.roomFailure({error: fakeError}); + + expect(store._storeState.roomState).eql(ROOM_STATES.FAILED); + expect(store._storeState.failureReason).eql(FAILURE_REASONS.EXPIRED_OR_INVALID); + }); }); describe("#setupWindowData", function() { @@ -117,6 +136,10 @@ roomUrl: "http://invalid" }; + store = new loop.store.ActiveRoomStore(dispatcher, { + mozLoop: fakeMozLoop, + sdkDriver: {} + }); fakeMozLoop.rooms.get. withArgs(fakeToken). callsArgOnWith(1, // index of callback argument @@ -138,7 +161,7 @@ to.have.property('roomState', ROOM_STATES.GATHER); }); - it("should dispatch an UpdateRoomInfo action if the get is successful", + it("should dispatch an SetupRoomInfo action if the get is successful", function() { store.setupWindowData(new sharedActions.SetupWindowData({ windowId: "42", @@ -148,7 +171,7 @@ sinon.assert.calledTwice(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, - new sharedActions.UpdateRoomInfo(_.extend({ + new sharedActions.SetupRoomInfo(_.extend({ roomToken: fakeToken }, fakeRoomData))); }); @@ -210,7 +233,7 @@ }); }); - describe("#updateRoomInfo", function() { + describe("#setupRoomInfo", function() { var fakeRoomInfo; beforeEach(function() { @@ -223,13 +246,13 @@ }); it("should set the state to READY", function() { - store.updateRoomInfo(new sharedActions.UpdateRoomInfo(fakeRoomInfo)); + store.setupRoomInfo(new sharedActions.SetupRoomInfo(fakeRoomInfo)); expect(store._storeState.roomState).eql(ROOM_STATES.READY); }); it("should save the room information", function() { - store.updateRoomInfo(new sharedActions.UpdateRoomInfo(fakeRoomInfo)); + store.setupRoomInfo(new sharedActions.SetupRoomInfo(fakeRoomInfo)); var state = store.getStoreState(); expect(state.roomName).eql(fakeRoomInfo.roomName); @@ -239,11 +262,40 @@ }); }); + describe("#updateRoomInfo", function() { + var fakeRoomInfo; + + beforeEach(function() { + fakeRoomInfo = { + roomName: "Its a room", + roomOwner: "Me", + roomUrl: "http://invalid" + }; + }); + + it("should save the room information", function() { + store.updateRoomInfo(new sharedActions.UpdateRoomInfo(fakeRoomInfo)); + + var state = store.getStoreState(); + expect(state.roomName).eql(fakeRoomInfo.roomName); + expect(state.roomOwner).eql(fakeRoomInfo.roomOwner); + expect(state.roomUrl).eql(fakeRoomInfo.roomUrl); + }); + }); + describe("#joinRoom", function() { beforeEach(function() { store.setStoreState({roomToken: "tokenFake"}); }); + it("should reset failureReason", function() { + store.setStoreState({failureReason: "Test"}); + + store.joinRoom(); + + expect(store.getStoreState().failureReason).eql(undefined); + }); + it("should call rooms.join on mozLoop", function() { store.joinRoom(); @@ -380,22 +432,34 @@ }); describe("#connectionFailure", function() { + var connectionFailureAction; + beforeEach(function() { store.setStoreState({ roomState: ROOM_STATES.JOINED, roomToken: "fakeToken", sessionToken: "1627384950" }); + + connectionFailureAction = new sharedActions.ConnectionFailure({ + reason: "FAIL" + }); + }); + + it("should store the failure reason", function() { + store.connectionFailure(connectionFailureAction); + + expect(store.getStoreState().failureReason).eql("FAIL"); }); it("should reset the multiplexGum", function() { - store.leaveRoom(); + store.connectionFailure(connectionFailureAction); sinon.assert.calledOnce(fakeMultiplexGum.reset); }); it("should disconnect from the servers via the sdk", function() { - store.connectionFailure(); + store.connectionFailure(connectionFailureAction); sinon.assert.calledOnce(fakeSdkDriver.disconnectSession); }); @@ -404,13 +468,13 @@ sandbox.stub(window, "clearTimeout"); store._timeout = {}; - store.connectionFailure(); + store.connectionFailure(connectionFailureAction); sinon.assert.calledOnce(clearTimeout); }); it("should call mozLoop.rooms.leave", function() { - store.connectionFailure(); + store.connectionFailure(connectionFailureAction); sinon.assert.calledOnce(fakeMozLoop.rooms.leave); sinon.assert.calledWithExactly(fakeMozLoop.rooms.leave, @@ -418,7 +482,7 @@ }); it("should set the state to `FAILED`", function() { - store.connectionFailure(); + store.connectionFailure(connectionFailureAction); expect(store.getStoreState().roomState).eql(ROOM_STATES.FAILED); }); @@ -454,6 +518,14 @@ expect(store.getStoreState().roomState).eql(ROOM_STATES.HAS_PARTICIPANTS); }); + + it("should set the pref for ToS to `seen`", function() { + store.remotePeerConnected(); + + sinon.assert.calledOnce(fakeMozLoop.setLoopPref); + sinon.assert.calledWithExactly(fakeMozLoop.setLoopPref, + "seenToS", "seen"); + }); }); describe("#remotePeerDisconnected", function() { @@ -502,10 +574,10 @@ "fakeToken", "1627384950"); }); - it("should set the state to ready", function() { + it("should set the state to ENDED", function() { store.windowUnload(); - expect(store._storeState.roomState).eql(ROOM_STATES.READY); + expect(store._storeState.roomState).eql(ROOM_STATES.ENDED); }); }); @@ -547,10 +619,39 @@ "fakeToken", "1627384950"); }); - it("should set the state to ready", function() { + it("should set the state to ENDED", function() { store.leaveRoom(); - expect(store._storeState.roomState).eql(ROOM_STATES.READY); + expect(store._storeState.roomState).eql(ROOM_STATES.ENDED); + }); + }); + + describe("Events", function() { + describe("update:{roomToken}", function() { + beforeEach(function() { + store.setupRoomInfo(new sharedActions.SetupRoomInfo({ + roomName: "Its a room", + roomOwner: "Me", + roomToken: "fakeToken", + roomUrl: "http://invalid" + })); + }); + + it("should dispatch an UpdateRoomInfo action", function() { + sinon.assert.calledOnce(fakeMozLoop.rooms.on); + + var fakeRoomData = { + roomName: "fakeName", + roomOwner: "you", + roomUrl: "original" + }; + + fakeMozLoop.rooms.on.callArgWith(1, "update", fakeRoomData); + + sinon.assert.calledOnce(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.UpdateRoomInfo(fakeRoomData)); + }); }); }); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/conversationStore_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/conversationStore_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/conversationStore_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/conversationStore_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -37,7 +37,7 @@ }; navigator.mozLoop = { - getLoopBoolPref: sandbox.stub(), + getLoopPref: sandbox.stub(), calls: { setCallInProgress: sandbox.stub(), clearCallInProgress: sandbox.stub() diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/feedbackStore_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/feedbackStore_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/feedbackStore_test.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/feedbackStore_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -0,0 +1,108 @@ +/* global chai, loop */ + +var expect = chai.expect; +var sharedActions = loop.shared.actions; + +describe("loop.store.FeedbackStore", function () { + "use strict"; + + var FEEDBACK_STATES = loop.store.FEEDBACK_STATES; + var sandbox, dispatcher, store, feedbackClient; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + + dispatcher = new loop.Dispatcher(); + + feedbackClient = new loop.FeedbackAPIClient("http://invalid", { + product: "Loop" + }); + + store = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: feedbackClient + }); + }); + + afterEach(function() { + sandbox.restore(); + }); + + describe("#constructor", function() { + it("should throw an error if feedbackClient is missing", function() { + expect(function() { + new loop.store.FeedbackStore(dispatcher); + }).to.Throw(/feedbackClient/); + }); + + it("should set the store to the INIT feedback state", function() { + var store = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: feedbackClient + }); + + expect(store.getStoreState("feedbackState")).eql(FEEDBACK_STATES.INIT); + }); + }); + + describe("#requireFeedbackDetails", function() { + it("should transition to DETAILS state", function() { + store.requireFeedbackDetails(new sharedActions.RequireFeedbackDetails()); + + expect(store.getStoreState("feedbackState")).eql(FEEDBACK_STATES.DETAILS); + }); + }); + + describe("#sendFeedback", function() { + var sadFeedbackData = { + happy: false, + category: "fakeCategory", + description: "fakeDescription" + }; + + beforeEach(function() { + store.requireFeedbackDetails(); + }); + + it("should send feedback data over the feedback client", function() { + sandbox.stub(feedbackClient, "send"); + + store.sendFeedback(new sharedActions.SendFeedback(sadFeedbackData)); + + sinon.assert.calledOnce(feedbackClient.send); + sinon.assert.calledWithMatch(feedbackClient.send, sadFeedbackData); + }); + + it("should transition to PENDING state", function() { + sandbox.stub(feedbackClient, "send"); + + store.sendFeedback(new sharedActions.SendFeedback(sadFeedbackData)); + + expect(store.getStoreState("feedbackState")).eql(FEEDBACK_STATES.PENDING); + }); + + it("should transition to SENT state on successful submission", function(done) { + sandbox.stub(feedbackClient, "send", function(data, cb) { + cb(null); + }); + + store.once("change:feedbackState", function() { + expect(store.getStoreState("feedbackState")).eql(FEEDBACK_STATES.SENT); + done(); + }); + + store.sendFeedback(new sharedActions.SendFeedback(sadFeedbackData)); + }); + + it("should transition to FAILED state on failed submission", function(done) { + sandbox.stub(feedbackClient, "send", function(data, cb) { + cb(new Error("failed")); + }); + + store.once("change:feedbackState", function() { + expect(store.getStoreState("feedbackState")).eql(FEEDBACK_STATES.FAILED); + done(); + }); + + store.sendFeedback(new sharedActions.SendFeedback(sadFeedbackData)); + }); + }); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/feedbackViews_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/feedbackViews_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/feedbackViews_test.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/feedbackViews_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -0,0 +1,196 @@ +/* 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/. */ + +/*global loop, sinon, React */ +/* jshint newcap:false */ + +var expect = chai.expect; +var l10n = navigator.mozL10n || document.mozL10n; +var TestUtils = React.addons.TestUtils; +var sharedActions = loop.shared.actions; +var sharedViews = loop.shared.views; + +var FEEDBACK_STATES = loop.store.FEEDBACK_STATES; + +describe("loop.shared.views.FeedbackView", function() { + "use strict"; + + var sandbox, comp, dispatcher, fakeFeedbackClient, feedbackStore; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + dispatcher = new loop.Dispatcher(); + fakeFeedbackClient = {send: sandbox.stub()}; + feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: fakeFeedbackClient + }); + comp = TestUtils.renderIntoDocument(sharedViews.FeedbackView({ + feedbackStore: feedbackStore + })); + }); + + afterEach(function() { + sandbox.restore(); + }); + + // local test helpers + function clickHappyFace(comp) { + var happyFace = comp.getDOMNode().querySelector(".face-happy"); + TestUtils.Simulate.click(happyFace); + } + + function clickSadFace(comp) { + var sadFace = comp.getDOMNode().querySelector(".face-sad"); + TestUtils.Simulate.click(sadFace); + } + + function fillSadFeedbackForm(comp, category, text) { + TestUtils.Simulate.change( + comp.getDOMNode().querySelector("[value='" + category + "']")); + + if (text) { + TestUtils.Simulate.change( + comp.getDOMNode().querySelector("[name='description']"), { + target: {value: "fake reason"} + }); + } + } + + function submitSadFeedbackForm(comp, category, text) { + TestUtils.Simulate.submit(comp.getDOMNode().querySelector("form")); + } + + describe("Happy feedback", function() { + it("should dispatch a SendFeedback action", function() { + var dispatch = sandbox.stub(dispatcher, "dispatch"); + + clickHappyFace(comp); + + sinon.assert.calledWithMatch(dispatch, new sharedActions.SendFeedback({ + happy: true, + category: "", + description: "" + })); + }); + + it("should thank the user once feedback data is sent", function() { + feedbackStore.setStoreState({feedbackState: FEEDBACK_STATES.SENT}); + + expect(comp.getDOMNode().querySelectorAll(".thank-you")).not.eql(null); + expect(comp.getDOMNode().querySelector("button.fx-embedded-btn-back")) + .eql(null); + }); + }); + + describe("Sad feedback", function() { + it("should bring the user to feedback form when clicking on the sad face", + function() { + clickSadFace(comp); + + expect(comp.getDOMNode().querySelectorAll("form")).not.eql(null); + }); + + it("should render a back button", function() { + feedbackStore.setStoreState({feedbackState: FEEDBACK_STATES.DETAILS}); + + expect(comp.getDOMNode().querySelector("button.fx-embedded-btn-back")) + .not.eql(null); + }); + + it("should reset the view when clicking the back button", function() { + feedbackStore.setStoreState({feedbackState: FEEDBACK_STATES.DETAILS}); + + TestUtils.Simulate.click( + comp.getDOMNode().querySelector("button.fx-embedded-btn-back")); + + expect(comp.getDOMNode().querySelector(".faces")).not.eql(null); + }); + + it("should disable the form submit button when no category is chosen", + function() { + clickSadFace(comp); + + expect(comp.getDOMNode().querySelector("form button").disabled).eql(true); + }); + + it("should disable the form submit button when the 'other' category is " + + "chosen but no description has been entered yet", + function() { + clickSadFace(comp); + fillSadFeedbackForm(comp, "other"); + + expect(comp.getDOMNode().querySelector("form button").disabled).eql(true); + }); + + it("should enable the form submit button when the 'other' category is " + + "chosen and a description is entered", + function() { + clickSadFace(comp); + fillSadFeedbackForm(comp, "other", "fake"); + + expect(comp.getDOMNode().querySelector("form button").disabled).eql(false); + }); + + it("should empty the description field when a predefined category is " + + "chosen", + function() { + clickSadFace(comp); + + fillSadFeedbackForm(comp, "confusing"); + + expect(comp.getDOMNode().querySelector(".feedback-description").value).eql(""); + }); + + it("should enable the form submit button once a predefined category is " + + "chosen", + function() { + clickSadFace(comp); + + fillSadFeedbackForm(comp, "confusing"); + + expect(comp.getDOMNode().querySelector("form button").disabled).eql(false); + }); + + it("should send feedback data when the form is submitted", function() { + var dispatch = sandbox.stub(dispatcher, "dispatch"); + feedbackStore.setStoreState({feedbackState: FEEDBACK_STATES.DETAILS}); + fillSadFeedbackForm(comp, "confusing"); + + submitSadFeedbackForm(comp); + + sinon.assert.calledOnce(dispatch); + sinon.assert.calledWithMatch(dispatch, new sharedActions.SendFeedback({ + happy: false, + category: "confusing", + description: "" + })); + }); + + it("should send feedback data when user has entered a custom description", + function() { + clickSadFace(comp); + + fillSadFeedbackForm(comp, "other", "fake reason"); + submitSadFeedbackForm(comp); + + sinon.assert.calledOnce(fakeFeedbackClient.send); + sinon.assert.calledWith(fakeFeedbackClient.send, { + happy: false, + category: "other", + description: "fake reason" + }); + }); + + it("should thank the user when feedback data has been sent", function() { + fakeFeedbackClient.send = function(data, cb) { + cb(); + }; + clickSadFace(comp); + fillSadFeedbackForm(comp, "confusing"); + submitSadFeedbackForm(comp); + + expect(comp.getDOMNode().querySelectorAll(".thank-you")).not.eql(null); + }); + }); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/index.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/index.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/shared/index.html 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/shared/index.html 2014-11-26 21:45:48.000000000 +0000 @@ -43,9 +43,12 @@ + - + + + @@ -54,11 +57,14 @@ + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/standalone/standaloneMozLoop_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/standalone/standaloneMozLoop_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/standalone/standaloneMozLoop_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/standalone/standaloneMozLoop_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -46,6 +46,36 @@ }); }); + describe("#setLoopPref", function() { + afterEach(function() { + localStorage.removeItem("fakePref"); + }); + + it("should store the value of the preference", function() { + mozLoop.setLoopPref("fakePref", "fakeValue"); + + expect(localStorage.getItem("fakePref")).eql("fakeValue"); + }); + + it("should not store the value of seenToS", function() { + mozLoop.setLoopPref("seenToS", "fakeValue1"); + + expect(localStorage.getItem("seenToS")).eql(null); + }); + }); + + describe("#getLoopPref", function() { + afterEach(function() { + localStorage.removeItem("fakePref"); + }); + + it("should return the value of the preference", function() { + localStorage.setItem("fakePref", "fakeValue"); + + expect(mozLoop.getLoopPref("fakePref")).eql("fakeValue"); + }); + }); + describe("#rooms.join", function() { it("should POST to the server", function() { mozLoop.rooms.join("fakeToken", callback); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/standalone/standaloneRoomViews_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/standalone/standaloneRoomViews_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/standalone/standaloneRoomViews_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/standalone/standaloneRoomViews_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -18,8 +18,7 @@ sandbox = sinon.sandbox.create(); dispatcher = new loop.Dispatcher(); dispatch = sandbox.stub(dispatcher, "dispatch"); - activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: {}, sdkDriver: {} }); @@ -39,27 +38,42 @@ })); } + function expectActionDispatched(view) { + sinon.assert.calledOnce(dispatch); + sinon.assert.calledWithExactly(dispatch, + sinon.match.instanceOf(sharedActions.SetupStreamElements)); + sinon.assert.calledWithExactly(dispatch, sinon.match(function(value) { + return value.getLocalElementFunc() === + view.getDOMNode().querySelector(".local"); + })); + sinon.assert.calledWithExactly(dispatch, sinon.match(function(value) { + return value.getRemoteElementFunc() === + view.getDOMNode().querySelector(".remote"); + })); + } + describe("#componentWillUpdate", function() { - it("dispatch an `SetupStreamElements` action on room joined", function() { - activeRoomStore.setStoreState({roomState: ROOM_STATES.READY}); - var view = mountTestComponent(); + it("should dispatch a `SetupStreamElements` action on room joined", + function() { + activeRoomStore.setStoreState({roomState: ROOM_STATES.READY}); + var view = mountTestComponent(); - sinon.assert.notCalled(dispatch); + sinon.assert.notCalled(dispatch); - activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED}); + activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED}); - sinon.assert.calledOnce(dispatch); - sinon.assert.calledWithExactly(dispatch, - sinon.match.instanceOf(sharedActions.SetupStreamElements)); - sinon.assert.calledWithExactly(dispatch, sinon.match(function(value) { - return value.getLocalElementFunc() === - view.getDOMNode().querySelector(".local"); - })); - sinon.assert.calledWithExactly(dispatch, sinon.match(function(value) { - return value.getRemoteElementFunc() === - view.getDOMNode().querySelector(".remote"); - })); - }); + expectActionDispatched(view); + }); + + it("should dispatch a `SetupStreamElements` action on room rejoined", + function() { + activeRoomStore.setStoreState({roomState: ROOM_STATES.ENDED}); + var view = mountTestComponent(); + + activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED}); + + expectActionDispatched(view); + }); }); describe("#publishStream", function() { @@ -138,6 +152,16 @@ .not.eql(null); }); }); + + describe("Failed room message", function() { + it("should display a failed room message on FAILED", + function() { + activeRoomStore.setStoreState({roomState: ROOM_STATES.FAILED}); + + expect(view.getDOMNode().querySelector(".failed-room-message")) + .not.eql(null); + }); + }); describe("Join button", function() { function getJoinButton(view) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/standalone/webapp_test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/standalone/webapp_test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/standalone/webapp_test.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/standalone/webapp_test.js 2014-11-26 21:45:48.000000000 +0000 @@ -19,14 +19,20 @@ notifications, feedbackApiClient, stubGetPermsAndCacheMedia, - fakeAudioXHR; + fakeAudioXHR, + dispatcher, + feedbackStore; beforeEach(function() { sandbox = sinon.sandbox.create(); + dispatcher = new loop.Dispatcher(); notifications = new sharedModels.NotificationCollection(); feedbackApiClient = new loop.FeedbackAPIClient("http://invalid", { product: "Loop" }); + feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }); stubGetPermsAndCacheMedia = sandbox.stub( loop.standaloneMedia._MultiplexGum.prototype, "getPermsAndCacheMedia"); @@ -123,7 +129,7 @@ conversation: conversation, notifications: notifications, sdk: {}, - feedbackApiClient: feedbackApiClient + feedbackStore: feedbackStore }); }); @@ -363,6 +369,16 @@ }); describe("session:ended", function() { + it("should call multiplexGum.reset", function() { + var multiplexGum = new standaloneMedia._MultiplexGum(); + standaloneMedia.setSingleton(multiplexGum); + sandbox.stub(standaloneMedia._MultiplexGum.prototype, "reset"); + + conversation.trigger("session:ended"); + + sinon.assert.calledOnce(multiplexGum.reset); + }); + it("should display the StartConversationView", function() { conversation.trigger("session:ended"); @@ -468,14 +484,14 @@ }); it("should display the FailedConversationView", function() { - conversation.setupOutgoingCall(); + ocView.setupOutgoingCall(); TestUtils.findRenderedComponentWithType(ocView, loop.webapp.FailedConversationView); }); it("should display an error", function() { - conversation.setupOutgoingCall(); + ocView.setupOutgoingCall(); sinon.assert.calledOnce(notifications.errorL10n); }); @@ -488,7 +504,8 @@ it("should call requestCallInfo on the client", function() { - conversation.setupOutgoingCall("audio-video"); + conversation.set("selectedCallType", "audio-video"); + ocView.setupOutgoingCall(); sinon.assert.calledOnce(client.requestCallInfo); sinon.assert.calledWith(client.requestCallInfo, "fakeToken", @@ -500,7 +517,7 @@ function() { client.requestCallInfo.callsArgWith(2, {errno: 105}); - conversation.setupOutgoingCall(); + ocView.setupOutgoingCall(); TestUtils.findRenderedComponentWithType(ocView, loop.webapp.CallUrlExpiredView); @@ -510,7 +527,7 @@ function() { client.requestCallInfo.callsArgWith(2, {errno: 104}); - conversation.setupOutgoingCall(); + ocView.setupOutgoingCall(); TestUtils.findRenderedComponentWithType(ocView, loop.webapp.FailedConversationView); @@ -519,7 +536,7 @@ it("should notify the user on any other error", function() { client.requestCallInfo.callsArgWith(2, {errno: 104}); - conversation.setupOutgoingCall(); + ocView.setupOutgoingCall(); sinon.assert.calledOnce(notifications.errorL10n); }); @@ -528,7 +545,7 @@ "are successfully received", function() { client.requestCallInfo.callsArgWith(2, null, fakeSessionData); - conversation.setupOutgoingCall(); + ocView.setupOutgoingCall(); sinon.assert.calledOnce(conversation.outgoing); sinon.assert.calledWithExactly(conversation.outgoing, fakeSessionData); @@ -536,6 +553,52 @@ }); }); }); + + describe("getMediaPrivs", function() { + var multiplexGum; + + beforeEach(function() { + multiplexGum = new standaloneMedia._MultiplexGum(); + standaloneMedia.setSingleton(multiplexGum); + sandbox.stub(standaloneMedia._MultiplexGum.prototype, "reset"); + + sandbox.stub(conversation, "gotMediaPrivs"); + }); + + it("should call getPermsAndCacheMedia", function() { + conversation.trigger("call:outgoing:get-media-privs"); + + sinon.assert.calledOnce(stubGetPermsAndCacheMedia); + }); + + it("should call gotMediaPrevs on the model when successful", function() { + stubGetPermsAndCacheMedia.callsArgWith(1, {}); + + conversation.trigger("call:outgoing:get-media-privs"); + + sinon.assert.calledOnce(conversation.gotMediaPrivs); + }); + + it("should call multiplexGum.reset when getPermsAndCacheMedia fails", + function() { + stubGetPermsAndCacheMedia.callsArgWith(2, "FAKE_ERROR"); + + conversation.trigger("call:outgoing:get-media-privs"); + + sinon.assert.calledOnce(multiplexGum.reset); + }); + + it("should set state to `failure` when getPermsAndCacheMedia fails", + function() { + stubGetPermsAndCacheMedia.callsArgWith(2, "FAKE_ERROR"); + + conversation.trigger("call:outgoing:get-media-privs"); + + expect(ocView.state.callStatus).eql("failure"); + }); + }); + + }); describe("FailedConversationView", function() { @@ -582,7 +645,7 @@ describe("WebappRootView", function() { var helper, sdk, conversationModel, client, props, standaloneAppStore; - var dispatcher, activeRoomStore; + var activeRoomStore; function mountTestComponent() { return TestUtils.renderIntoDocument( @@ -609,9 +672,7 @@ client = new loop.StandaloneClient({ baseServerUrl: "fakeUrl" }); - dispatcher = new loop.Dispatcher(); - activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: {}, sdkDriver: {} }); @@ -689,7 +750,7 @@ }); }); - describe("PendingConversationView", function() { + describe("WaitingConversationView", function() { var view, websocket, fakeAudio; beforeEach(function() { @@ -709,7 +770,7 @@ sandbox.stub(window, "XMLHttpRequest").returns(fakeAudioXHR); view = React.addons.TestUtils.renderIntoDocument( - loop.webapp.PendingConversationView({ + loop.webapp.WaitingConversationView({ websocket: websocket }) ); @@ -798,27 +859,8 @@ client: standaloneClientStub }) ); - - // default to succeeding with a null local media object - stubGetPermsAndCacheMedia.callsArgWith(1, {}); }); - it("should fire multiplexGum.reset when getPermsAndCacheMedia calls" + - " back an error", - function() { - var setupOutgoingCall = sinon.stub(conversation, "setupOutgoingCall"); - var multiplexGum = new standaloneMedia._MultiplexGum(); - standaloneMedia.setSingleton(multiplexGum); - sandbox.stub(standaloneMedia._MultiplexGum.prototype, "reset"); - stubGetPermsAndCacheMedia.callsArgWith(2, "FAKE_ERROR"); - - var button = view.getDOMNode().querySelector(".btn-accept"); - React.addons.TestUtils.Simulate.click(button); - - sinon.assert.calledOnce(multiplexGum.reset); - sinon.assert.calledWithExactly(multiplexGum.reset); - }); - it("should start the audio-video conversation establishment process", function() { var setupOutgoingCall = sinon.stub(conversation, "setupOutgoingCall"); @@ -1040,7 +1082,7 @@ loop.webapp.EndedConversationView({ conversation: conversation, sdk: {}, - feedbackApiClient: feedbackApiClient, + feedbackStore: feedbackStore, onAfterFeedbackReceived: function(){} }) ); @@ -1053,22 +1095,6 @@ it("should render a FeedbackView", function() { TestUtils.findRenderedComponentWithType(view, sharedViews.FeedbackView); }); - - describe("#componentDidMount", function() { - - it("should play a terminating sound, once", function() { - fakeAudioXHR.onload(); - - sinon.assert.called(fakeAudioXHR.open); - sinon.assert.calledWithExactly( - fakeAudioXHR.open, "GET", "shared/sounds/terminated.ogg", true); - - sinon.assert.calledOnce(fakeAudio.play); - expect(fakeAudio.loop).to.not.equal(true); - }); - - }); - }); describe("PromoteFirefoxView", function() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/head.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/head.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/head.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/head.js 2014-11-26 21:45:48.000000000 +0000 @@ -73,7 +73,7 @@ } function getLoopString(stringID) { - return MozLoopServiceInternal.localizedStrings[stringID].textContent; + return MozLoopServiceInternal.localizedStrings.get(stringID); } /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_looprooms.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_looprooms.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_looprooms.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_looprooms.js 2014-11-26 21:45:48.000000000 +0000 @@ -209,16 +209,22 @@ res.finish(); } + function getJSONData(body) { + return JSON.parse(CommonUtils.readBytesFromInputStream(body)); + } + // Add a request handler for each room in the list. [...kRooms.values()].forEach(function(room) { loopServer.registerPathHandler("/rooms/" + encodeURIComponent(room.roomToken), (req, res) => { if (req.method == "POST") { - let body = CommonUtils.readBytesFromInputStream(req.bodyInputStream); - let data = JSON.parse(body); + let data = getJSONData(req.bodyInputStream); res.setStatusLine(null, 200, "OK"); res.write(JSON.stringify(data)); res.processAsync(); res.finish(); + } else if (req.method == "PATCH") { + let data = getJSONData(req.bodyInputStream); + returnRoomDetails(res, data.roomName); } else { returnRoomDetails(res, room.roomName); } @@ -293,8 +299,8 @@ Assert.ok(openedUrl, "should open a chat window"); - // Stop the busy kicking in for following tests. - let windowId = openedUrl.match(/about:loopconversation\#(\d+)$/)[1]; + // Stop the busy kicking in for following tests. (note: windowId can be 'fakeToken') + let windowId = openedUrl.match(/about:loopconversation\#(\w+)$/)[1]; let windowData = MozLoopService.getConversationWindowData(windowId); Assert.equal(windowData.type, "room", "window data should contain room as the type"); @@ -331,6 +337,13 @@ }); // Test if joining a room works as expected. +add_task(function* test_joinRoomGuest() { + // We need these set up for getting the email address. + let roomToken = "_nxD4V4FflQ"; + let joinedData = yield LoopRooms.promise("join", roomToken); + Assert.equal(joinedData.action, "join"); +}); + add_task(function* test_joinRoom() { // We need these set up for getting the email address. Services.prefs.setCharPref("loop.fxa_oauth.profile", JSON.stringify({ @@ -344,6 +357,9 @@ let joinedData = yield LoopRooms.promise("join", roomToken); Assert.equal(joinedData.action, "join"); Assert.equal(joinedData.displayName, "fake@invalid.com"); + + Services.prefs.clearUserPref("loop.fxa_oauth.profile"); + Services.prefs.clearUserPref("loop.fxa_oauth.tokendata"); }); // Test if refreshing a room works as expected. @@ -363,6 +379,13 @@ Assert.equal(leaveData.sessionToken, "fakeLeaveSessionToken"); }); +// Test if renaming a room works as expected. +add_task(function* test_renameRoom() { + let roomToken = "_nxD4V4FflQ"; + let renameData = yield LoopRooms.promise("rename", roomToken, "fakeName"); + Assert.equal(renameData.roomName, "fakeName"); +}); + // Test if the event emitter implementation doesn't leak and is working as expected. add_task(function* () { Assert.strictEqual(gExpectedAdds.length, 0, "No room additions should be expected anymore"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_loopservice_hawk_errors.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_loopservice_hawk_errors.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_loopservice_hawk_errors.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_loopservice_hawk_errors.js 2014-11-26 21:45:48.000000000 +0000 @@ -37,7 +37,7 @@ add_task(function* error_offline() { Services.io.offline = true; - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, "/offline", "GET").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/offline", "GET").then( () => Assert.ok(false, "Should have rejected"), (error) => { MozLoopServiceInternal.setError("testing", error); @@ -58,7 +58,7 @@ add_task(function* guest_401() { Services.prefs.setCharPref("loop.hawk-session-token", "guest"); Services.prefs.setCharPref("loop.hawk-session-token.fxa", "fxa"); - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, "/401", "POST").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/401", "POST").then( () => Assert.ok(false, "Should have rejected"), (error) => { Assert.strictEqual(Services.prefs.getPrefType("loop.hawk-session-token"), @@ -83,7 +83,7 @@ add_task(function* fxa_401() { Services.prefs.setCharPref("loop.hawk-session-token", "guest"); Services.prefs.setCharPref("loop.hawk-session-token.fxa", "fxa"); - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.FXA, "/401", "POST").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.FXA, "/401", "POST").then( () => Assert.ok(false, "Should have rejected"), (error) => { Assert.strictEqual(Services.prefs.getCharPref("loop.hawk-session-token"), @@ -105,7 +105,7 @@ add_task(cleanup_between_tests); add_task(function* error_404() { - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, "/404", "GET").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/404", "GET").then( () => Assert.ok(false, "Should have rejected"), (error) => { MozLoopServiceInternal.setError("testing", error); @@ -122,7 +122,7 @@ add_task(cleanup_between_tests); add_task(function* error_500() { - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, "/500", "GET").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/500", "GET").then( () => Assert.ok(false, "Should have rejected"), (error) => { MozLoopServiceInternal.setError("testing", error); @@ -139,7 +139,7 @@ add_task(cleanup_between_tests); add_task(function* profile_500() { - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, "/500", "GET").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/500", "GET").then( () => Assert.ok(false, "Should have rejected"), (error) => { MozLoopServiceInternal.setError("profile", error); @@ -156,7 +156,7 @@ add_task(cleanup_between_tests); add_task(function* error_503() { - yield MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, "/503", "GET").then( + yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/503", "GET").then( () => Assert.ok(false, "Should have rejected"), (error) => { MozLoopServiceInternal.setError("testing", error); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js 2014-11-26 21:45:48.000000000 +0000 @@ -6,39 +6,39 @@ var fakeBoolPrefName = "boolean"; var fakePrefValue = "green"; -function test_getLoopCharPref() +function test_getLoopPref() { Services.prefs.setCharPref("loop." + fakeCharPrefName, fakePrefValue); - var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName); + var returnedPref = MozLoopService.getLoopPref(fakeCharPrefName, Ci.nsIPrefBranch.PREF_STRING); Assert.equal(returnedPref, fakePrefValue, "Should return a char pref under the loop. branch"); Services.prefs.clearUserPref("loop." + fakeCharPrefName); } -function test_getLoopCharPref_not_found() +function test_getLoopPref_not_found() { - var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName); + var returnedPref = MozLoopService.getLoopPref(fakeCharPrefName); Assert.equal(returnedPref, null, "Should return null if a preference is not found"); } -function test_getLoopCharPref_non_coercible_type() +function test_getLoopPref_non_coercible_type() { Services.prefs.setBoolPref("loop." + fakeCharPrefName, false); - var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName); + var returnedPref = MozLoopService.getLoopPref(fakeCharPrefName, Ci.nsIPrefBranch.PREF_STRING); Assert.equal(returnedPref, null, "Should return null if the preference exists & is of a non-coercible type"); } -function test_setLoopCharPref() +function test_setLoopPref() { Services.prefs.setCharPref("loop." + fakeCharPrefName, "red"); - MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue); + MozLoopService.setLoopPref(fakeCharPrefName, fakePrefValue); var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName); @@ -47,10 +47,10 @@ Services.prefs.clearUserPref("loop." + fakeCharPrefName); } -function test_setLoopCharPref_new() +function test_setLoopPref_new() { Services.prefs.clearUserPref("loop." + fakeCharPrefName); - MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue); + MozLoopService.setLoopPref(fakeCharPrefName, fakePrefValue, Ci.nsIPrefBranch.PREF_STRING); var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName); @@ -59,28 +59,28 @@ Services.prefs.clearUserPref("loop." + fakeCharPrefName); } -function test_setLoopCharPref_non_coercible_type() +function test_setLoopPref_non_coercible_type() { - MozLoopService.setLoopCharPref(fakeCharPrefName, true); + MozLoopService.setLoopPref(fakeCharPrefName, true); ok(true, "Setting non-coercible type should not fail"); } -function test_getLoopBoolPref() +function test_getLoopPref_bool() { Services.prefs.setBoolPref("loop." + fakeBoolPrefName, true); - var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName); + var returnedPref = MozLoopService.getLoopPref(fakeBoolPrefName); Assert.equal(returnedPref, true, "Should return a bool pref under the loop. branch"); Services.prefs.clearUserPref("loop." + fakeBoolPrefName); } -function test_getLoopBoolPref_not_found() +function test_getLoopPref_not_found_bool() { - var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName); + var returnedPref = MozLoopService.getLoopPref(fakeBoolPrefName); Assert.equal(returnedPref, null, "Should return null if a preference is not found"); @@ -91,15 +91,15 @@ { setupFakeLoopServer(); - test_getLoopCharPref(); - test_getLoopCharPref_not_found(); - test_getLoopCharPref_non_coercible_type(); - test_setLoopCharPref(); - test_setLoopCharPref_new(); - test_setLoopCharPref_non_coercible_type(); + test_getLoopPref(); + test_getLoopPref_not_found(); + test_getLoopPref_non_coercible_type(); + test_setLoopPref(); + test_setLoopPref_new(); + test_setLoopPref_non_coercible_type(); - test_getLoopBoolPref(); - test_getLoopBoolPref_not_found(); + test_getLoopPref_bool(); + test_getLoopPref_not_found_bool(); do_register_cleanup(function() { Services.prefs.clearUserPref("loop." + fakeCharPrefName); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_loopservice_token_validation.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_loopservice_token_validation.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/test/xpcshell/test_loopservice_token_validation.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/test/xpcshell/test_loopservice_token_validation.js 2014-11-26 21:45:48.000000000 +0000 @@ -20,7 +20,7 @@ do_throw("should not succeed with a bogus token"); }, err => { - Assert.equal(err, "session-token-wrong-size", "Should cause an error to be" + + Assert.equal(err.message, "session-token-wrong-size", "Should cause an error to be" + " called back if the session-token is not 64 characters long"); // for some reason, Assert.throw is misbehaving, so.... diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/fake-mozLoop.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/fake-mozLoop.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/fake-mozLoop.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/fake-mozLoop.js 2014-11-26 21:45:48.000000000 +0000 @@ -49,13 +49,14 @@ */ navigator.mozLoop = { ensureRegistered: function() {}, - getLoopCharPref: function() {}, - getLoopBoolPref: function(pref) { + getAudioBlob: function(){}, + getLoopPref: function(pref) { // Ensure UI for rooms is displayed in the showcase. if (pref === "rooms.enabled") { return true; } }, + setLoopPref: function(){}, releaseCallData: function() {}, copyString: function() {}, contacts: { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/index.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/index.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/index.html 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/index.html 2014-11-26 21:45:48.000000000 +0000 @@ -41,9 +41,12 @@ - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/ui-showcase.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/ui-showcase.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/ui-showcase.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/ui-showcase.js 2014-11-26 21:45:48.000000000 +0000 @@ -28,7 +28,8 @@ var UnsupportedBrowserView = loop.webapp.UnsupportedBrowserView; var UnsupportedDeviceView = loop.webapp.UnsupportedDeviceView; var CallUrlExpiredView = loop.webapp.CallUrlExpiredView; - var PendingConversationView = loop.webapp.PendingConversationView; + var GumPromptConversationView = loop.webapp.GumPromptConversationView; + var WaitingConversationView = loop.webapp.WaitingConversationView; var StartConversationView = loop.webapp.StartConversationView; var FailedConversationView = loop.webapp.FailedConversationView; var EndedConversationView = loop.webapp.EndedConversationView; @@ -39,8 +40,9 @@ var ConversationView = loop.shared.views.ConversationView; var FeedbackView = loop.shared.views.FeedbackView; - // Room constants + // Store constants var ROOM_STATES = loop.store.ROOM_STATES; + var FEEDBACK_STATES = loop.store.FEEDBACK_STATES; // Local helpers function returnTrue() { @@ -62,15 +64,16 @@ ); var dispatcher = new loop.Dispatcher(); - var activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: navigator.mozLoop, sdkDriver: {} }); - var roomStore = new loop.store.RoomStore({ - dispatcher: dispatcher, + var roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop }); + var feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: stageFeedbackApiClient + }); // Local mocks @@ -126,7 +129,7 @@ "audio", "audio-hover", "audio-active", "block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover", "contacts-active", "copy", "checkmark", "google", "google-hover", - "google-active", "history", "history-hover", "history-active", + "google-active", "history", "history-hover", "history-active", "leave", "precall", "precall-hover", "precall-active", "settings", "settings-hover", "settings-active", "tag", "tag-hover", "tag-active", "trash", "unblock", "unblock-hover", "unblock-active", "video", "video-hover", "video-active" @@ -324,16 +327,24 @@ ) ), - Section({name: "PendingConversationView"}, - Example({summary: "Pending conversation view (connecting)", dashed: "true"}, + Section({name: "GumPromptConversationView"}, + Example({summary: "Gum Prompt conversation view", dashed: "true"}, React.DOM.div({className: "standalone"}, - PendingConversationView({websocket: mockWebSocket, + GumPromptConversationView(null) + ) + ) + ), + + Section({name: "WaitingConversationView"}, + Example({summary: "Waiting conversation view (connecting)", dashed: "true"}, + React.DOM.div({className: "standalone"}, + WaitingConversationView({websocket: mockWebSocket, dispatcher: dispatcher}) ) ), - Example({summary: "Pending conversation view (ringing)", dashed: "true"}, + Example({summary: "Waiting conversation view (ringing)", dashed: "true"}, React.DOM.div({className: "standalone"}, - PendingConversationView({websocket: mockWebSocket, + WaitingConversationView({websocket: mockWebSocket, dispatcher: dispatcher, callState: "ringing"}) ) @@ -462,13 +473,13 @@ React.DOM.a({href: "https://input.allizom.org/"}, "input.allizom.org"), "." ), Example({summary: "Default (useable demo)", dashed: "true", style: {width: "260px"}}, - FeedbackView({feedbackApiClient: stageFeedbackApiClient}) + FeedbackView({feedbackStore: feedbackStore}) ), Example({summary: "Detailed form", dashed: "true", style: {width: "260px"}}, - FeedbackView({feedbackApiClient: stageFeedbackApiClient, step: "form"}) + FeedbackView({feedbackStore: feedbackStore, feedbackState: FEEDBACK_STATES.DETAILS}) ), Example({summary: "Thank you!", dashed: "true", style: {width: "260px"}}, - FeedbackView({feedbackApiClient: stageFeedbackApiClient, step: "finished"}) + FeedbackView({feedbackStore: feedbackStore, feedbackState: FEEDBACK_STATES.SENT}) ) ), @@ -488,7 +499,7 @@ video: {enabled: true}, audio: {enabled: true}, conversation: mockConversationModel, - feedbackApiClient: stageFeedbackApiClient, + feedbackStore: feedbackStore, onAfterFeedbackReceived: noop}) ) ) @@ -608,6 +619,16 @@ roomState: ROOM_STATES.FULL, helper: {isFirefox: returnFalse}}) ) + ), + + Example({summary: "Standalone room conversation (failed)"}, + React.DOM.div({className: "standalone"}, + StandaloneRoomView({ + dispatcher: dispatcher, + activeRoomStore: activeRoomStore, + roomState: ROOM_STATES.FAILED, + helper: {isFirefox: returnFalse}}) + ) ) ), diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/ui-showcase.jsx thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/ui-showcase.jsx --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/loop/ui/ui-showcase.jsx 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/loop/ui/ui-showcase.jsx 2014-11-26 21:45:48.000000000 +0000 @@ -28,7 +28,8 @@ var UnsupportedBrowserView = loop.webapp.UnsupportedBrowserView; var UnsupportedDeviceView = loop.webapp.UnsupportedDeviceView; var CallUrlExpiredView = loop.webapp.CallUrlExpiredView; - var PendingConversationView = loop.webapp.PendingConversationView; + var GumPromptConversationView = loop.webapp.GumPromptConversationView; + var WaitingConversationView = loop.webapp.WaitingConversationView; var StartConversationView = loop.webapp.StartConversationView; var FailedConversationView = loop.webapp.FailedConversationView; var EndedConversationView = loop.webapp.EndedConversationView; @@ -39,8 +40,9 @@ var ConversationView = loop.shared.views.ConversationView; var FeedbackView = loop.shared.views.FeedbackView; - // Room constants + // Store constants var ROOM_STATES = loop.store.ROOM_STATES; + var FEEDBACK_STATES = loop.store.FEEDBACK_STATES; // Local helpers function returnTrue() { @@ -62,15 +64,16 @@ ); var dispatcher = new loop.Dispatcher(); - var activeRoomStore = new loop.store.ActiveRoomStore({ - dispatcher: dispatcher, + var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: navigator.mozLoop, sdkDriver: {} }); - var roomStore = new loop.store.RoomStore({ - dispatcher: dispatcher, + var roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop }); + var feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: stageFeedbackApiClient + }); // Local mocks @@ -126,7 +129,7 @@ "audio", "audio-hover", "audio-active", "block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover", "contacts-active", "copy", "checkmark", "google", "google-hover", - "google-active", "history", "history-hover", "history-active", + "google-active", "history", "history-hover", "history-active", "leave", "precall", "precall-hover", "precall-active", "settings", "settings-hover", "settings-active", "tag", "tag-hover", "tag-active", "trash", "unblock", "unblock-hover", "unblock-active", "video", "video-hover", "video-active" @@ -324,16 +327,24 @@
-
- +
+
- +
+
+
+ +
+ +
+
- +
-
@@ -462,13 +473,13 @@ input.allizom.org.

- + - + - +
@@ -488,7 +499,7 @@ video={{enabled: true}} audio={{enabled: true}} conversation={mockConversationModel} - feedbackApiClient={stageFeedbackApiClient} + feedbackStore={feedbackStore} onAfterFeedbackReceived={noop} />
@@ -609,6 +620,16 @@ helper={{isFirefox: returnFalse}} />
+ + +
+ +
+
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/nsBrowserGlue.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/nsBrowserGlue.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/nsBrowserGlue.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/nsBrowserGlue.js 2014-11-26 21:45:48.000000000 +0000 @@ -2527,11 +2527,14 @@ } catch(e) {} let isHardwareAccelerated = true; + // Linux and Windows are currently ok, mac not so much. +#ifdef XP_MACOSX try { let win = RecentWindow.getMostRecentBrowserWindow(); let winutils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); isHardwareAccelerated = winutils.layerManagerType != "Basic"; } catch (e) {} +#endif if (!Services.appinfo.inSafeMode && !Services.appinfo.accessibilityEnabled && diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/preferences/in-content/privacy.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/preferences/in-content/privacy.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/preferences/in-content/privacy.xul 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/preferences/in-content/privacy.xul 2014-11-26 21:45:48.000000000 +0000 @@ -241,7 +241,7 @@ data-category="panePrivacy" hidden="true"> - + - + { + gBrowser.addEventListener("load", function onLoadListener(aEvent) { + let cw = aEvent.target.defaultView; + let tab = gBrowser._getTabForContentWindow(cw); + if (tab) { + info("onLoadListener: " + aEvent.originalTarget.location); + gBrowser.removeEventListener("load", onLoadListener, true); + resolve(aEvent); + } + }, true); + }); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/SessionHistory.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/SessionHistory.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/SessionHistory.jsm 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/SessionHistory.jsm 2014-11-26 21:45:49.000000000 +0000 @@ -187,8 +187,10 @@ // We will include the property only if it's truthy to save a couple of // bytes when the resulting object is stringified and saved to disk. - if (shEntry.referrerURI) + if (shEntry.referrerURI) { entry.referrer = shEntry.referrerURI.spec; + entry.referrerPolicy = shEntry.referrerPolicy; + } if (shEntry.srcdocData) entry.srcdocData = shEntry.srcdocData; @@ -340,8 +342,10 @@ shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory; if (entry.contentType) shEntry.contentType = entry.contentType; - if (entry.referrer) + if (entry.referrer) { shEntry.referrerURI = Utils.makeURI(entry.referrer); + shEntry.referrerPolicy = entry.referrerPolicy; + } if (entry.isSrcdocEntry) shEntry.srcdocData = entry.srcdocData; if (entry.baseURI) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/SessionStore.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/SessionStore.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/SessionStore.jsm 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/SessionStore.jsm 2014-11-26 21:45:49.000000000 +0000 @@ -74,6 +74,16 @@ "SessionStore:reloadPendingTab", ]; +// The list of messages we accept from s that have no tab +// assigned. Those are for example the ones that preload about:newtab pages. +const FMM_NOTAB_MESSAGES = new Set([ + // For a description see above. + "SessionStore:setupSyncHandler", + + // For a description see above. + "SessionStore:update", +]); + // Messages that will be received via the Parent Process Message Manager. const PPMM_MESSAGES = [ // A tab is being revived from the crashed state. The sender of this @@ -605,9 +615,12 @@ var browser = aMessage.target; var win = browser.ownerDocument.defaultView; let tab = win.gBrowser.getTabForBrowser(browser); - if (!tab) { - // Ignore messages from elements that are not tabs. - return; + + // Ensure we receive only specific messages from s that + // have no tab assigned, e.g. the ones that preload aobut:newtab pages. + if (!tab && !FMM_NOTAB_MESSAGES.has(aMessage.name)) { + throw new Error(`received unexpected message '${aMessage.name}' ` + + `from a browser that has no tab`); } switch (aMessage.name) { @@ -635,8 +648,21 @@ let uri = activePageData ? activePageData.url || null : null; browser.userTypedValue = uri; - // Update tab label and icon again after the tab history was updated. - this.updateTabLabelAndIcon(tab, tabData); + // If the page has a title, set it. + if (activePageData) { + if (activePageData.title) { + tab.label = activePageData.title; + tab.crop = "end"; + } else if (activePageData.url != "about:blank") { + tab.label = activePageData.url; + tab.crop = "center"; + } + } + + // Restore the tab icon. + if ("image" in tabData) { + win.gBrowser.setIcon(tab, tabData.image); + } let event = win.document.createEvent("Events"); event.initEvent("SSTabRestoring", true, false); @@ -691,7 +717,7 @@ } break; default: - debug(`received unknown message '${aMessage.name}'`); + throw new Error(`received unknown message '${aMessage.name}'`); break; } }, @@ -1847,26 +1873,6 @@ } }, - updateTabLabelAndIcon(tab, tabData) { - let activePageData = tabData.entries[tabData.index - 1] || null; - - // If the page has a title, set it. - if (activePageData) { - if (activePageData.title) { - tab.label = activePageData.title; - tab.crop = "end"; - } else if (activePageData.url != "about:blank") { - tab.label = activePageData.url; - tab.crop = "center"; - } - } - - // Restore the tab icon. - if ("image" in tabData) { - tab.ownerDocument.defaultView.gBrowser.setIcon(tab, tabData.image); - } - }, - /** * Restores the session state stored in LastSession. This will attempt * to merge data into the current session. If a window was opened at startup @@ -2539,17 +2545,9 @@ this._windows[aWindow.__SSi].selected = aSelectTab; } - // If we restore the selected tab, make sure it goes first. - let selectedIndex = aTabs.indexOf(tabbrowser.selectedTab); - if (selectedIndex > -1) { - this.restoreTab(tabbrowser.selectedTab, aTabData[selectedIndex]); - } - // Restore all tabs. for (let t = 0; t < aTabs.length; t++) { - if (t != selectedIndex) { - this.restoreTab(aTabs[t], aTabData[t]); - } + this.restoreTab(aTabs[t], aTabData[t]); } }, @@ -2655,10 +2653,6 @@ browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory", {tabData: tabData, epoch: epoch}); - // Update tab label and icon to show something - // while we wait for the messages to be processed. - this.updateTabLabelAndIcon(tab, tabData); - // Restore tab attributes. if ("attributes" in tabData) { TabAttributes.set(tab, tabData.attributes); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/test/browser_522545.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/test/browser_522545.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/test/browser_522545.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/test/browser_522545.js 2014-11-26 21:45:49.000000000 +0000 @@ -193,16 +193,16 @@ is(browser.userTypedValue, null, "userTypedValue is empty to start"); is(browser.userTypedClear, 0, "userTypedClear is 0 to start"); - gURLBar.value = "example.org"; - let event = document.createEvent("Events"); - event.initEvent("input", true, false); - gURLBar.dispatchEvent(event); + let inputText = "example.org"; + gURLBar.focus(); + gURLBar.value = inputText.slice(0, -1); + EventUtils.synthesizeKey(inputText.slice(-1) , {}); executeSoon(function () { is(browser.userTypedValue, "example.org", - "userTypedValue was set when changing gURLBar.value"); + "userTypedValue was set when changing URLBar value"); is(browser.userTypedClear, 0, - "userTypedClear was not changed when changing gURLBar.value"); + "userTypedClear was not changed when changing URLBar value"); // Now make sure ss gets these values too let newState = JSON.parse(ss.getBrowserState()); @@ -235,7 +235,7 @@ "userTypedValue was null after loading a URI"); is(browser.userTypedClear, 0, "userTypeClear reset to 0"); - is(gURLBar.value, gURLBar.trimValue("http://example.com/"), + is(gURLBar.textValue, gURLBar.trimValue("http://example.com/"), "Address bar's value set after loading URI"); runNextTest(); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/test/browser_586068-reload.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/test/browser_586068-reload.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/test/browser_586068-reload.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/test/browser_586068-reload.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,11 +9,6 @@ } function runTests() { - // Request a longer timeout because the test takes quite a while - // to complete on slow Windows debug machines and we would otherwise - // see a lot of (not so) intermittent test failures. - requestLongerTimeout(2); - Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true); registerCleanupFunction(function () { Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); @@ -29,112 +24,31 @@ { entries: [{ url: "http://example.org/#7" }], extData: { "uniq": r() } }, { entries: [{ url: "http://example.org/#8" }], extData: { "uniq": r() } }, { entries: [{ url: "http://example.org/#9" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#10" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#11" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#12" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#13" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#14" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#15" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#16" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#17" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.org/#18" }], extData: { "uniq": r() } } ], selected: 1 }] }; let loadCount = 0; - gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { - loadCount++; - is(aBrowser.currentURI.spec, state.windows[0].tabs[loadCount - 1].entries[0].url, - "load " + loadCount + " - browser loaded correct url"); - - if (loadCount <= state.windows[0].tabs.length) { - // double check that this tab was the right one - let expectedData = state.windows[0].tabs[loadCount - 1].extData.uniq; - let tab; - for (let i = 0; i < window.gBrowser.tabs.length; i++) { - if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser) - tab = window.gBrowser.tabs[i]; - } - is(ss.getTabValue(tab, "uniq"), expectedData, - "load " + loadCount + " - correct tab was restored"); - - if (loadCount == state.windows[0].tabs.length) { - gProgressListener.unsetCallback(); - executeSoon(function () { - reloadAllTabs(state, function () { - waitForBrowserState(TestRunner.backupState, testCascade); - }); - }); - } else { - // reload the next tab - window.gBrowser.reloadTab(window.gBrowser.tabs[loadCount]); - } - } - }); - - yield ss.setBrowserState(JSON.stringify(state)); -} - -function testCascade() { - Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false); - - let state = { windows: [{ tabs: [ - { entries: [{ url: "http://example.com/#1" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.com/#2" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.com/#3" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.com/#4" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.com/#5" }], extData: { "uniq": r() } }, - { entries: [{ url: "http://example.com/#6" }], extData: { "uniq": r() } } - ] }] }; - - let loadCount = 0; - gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { - if (++loadCount < state.windows[0].tabs.length) { - return; - } - - gProgressListener.unsetCallback(); - executeSoon(function () { - reloadAllTabs(state, next); - }); - }); + gBrowser.tabContainer.addEventListener("SSTabRestored", function onRestored(event) { + let tab = event.target; + let browser = tab.linkedBrowser; + let tabData = state.windows[0].tabs[loadCount++]; - ss.setBrowserState(JSON.stringify(state)); -} + // double check that this tab was the right one + is(browser.currentURI.spec, tabData.entries[0].url, + "load " + loadCount + " - browser loaded correct url"); + is(ss.getTabValue(tab, "uniq"), tabData.extData.uniq, + "load " + loadCount + " - correct tab was restored"); -function reloadAllTabs(aState, aCallback) { - // Simulate a left mouse button click with no modifiers, which is what - // Command-R, or clicking reload does. - let fakeEvent = { - button: 0, - metaKey: false, - altKey: false, - ctrlKey: false, - shiftKey: false - }; + if (loadCount == state.windows[0].tabs.length) { + gBrowser.tabContainer.removeEventListener("SSTabRestored", onRestored); - let loadCount = 0; - gWebProgressListener.setCallback(function (aBrowser) { - if (++loadCount <= aState.windows[0].tabs.length) { - // double check that this tab was the right one - let expectedData = aState.windows[0].tabs[loadCount - 1].extData.uniq; - let tab; - for (let i = 0; i < window.gBrowser.tabs.length; i++) { - if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser) - tab = window.gBrowser.tabs[i]; - } - is(ss.getTabValue(tab, "uniq"), expectedData, - "load " + loadCount + " - correct tab was reloaded"); - - if (loadCount == aState.windows[0].tabs.length) { - gWebProgressListener.unsetCallback(); - executeSoon(aCallback); - } else { - // reload the next tab - window.gBrowser.selectTabAtIndex(loadCount); - BrowserReloadOrDuplicate(fakeEvent); - } + executeSoon(function () { + waitForBrowserState(TestRunner.backupState, finish); + }); + } else { + // reload the next tab + gBrowser.browsers[loadCount].reload(); } }); - BrowserReloadOrDuplicate(fakeEvent); + yield ss.setBrowserState(JSON.stringify(state)); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/test/content.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/test/content.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/sessionstore/test/content.js 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/sessionstore/test/content.js 2014-11-26 21:45:49.000000000 +0000 @@ -82,7 +82,7 @@ // content-sessionStore.js. We run ours a little later to make sure // that the session store code has seen the event before we allow // the test to proceed. - executeSoon(() => sendSyncMessage("ss-test:MozStorageChanged")); + executeSoon(() => sendAsyncMessage("ss-test:MozStorageChanged")); }, true); addMessageListener("ss-test:modifySessionStorage", function (msg) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/shell/nsMacShellService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/shell/nsMacShellService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/shell/nsMacShellService.cpp 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/shell/nsMacShellService.cpp 2014-11-26 21:45:49.000000000 +0000 @@ -205,7 +205,9 @@ loadContext = do_QueryInterface(docShell); } - return wbp->SaveURI(imageURI, nullptr, docURI, nullptr, nullptr, + return wbp->SaveURI(imageURI, nullptr, + docURI, content->OwnerDoc()->GetReferrerPolicy(), + nullptr, nullptr, mBackgroundFile, loadContext); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/tabview/test/browser.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/tabview/test/browser.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/components/tabview/test/browser.ini 2014-11-14 09:37:13.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/components/tabview/test/browser.ini 2014-11-26 21:45:49.000000000 +0000 @@ -19,7 +19,7 @@ [browser_tabview_bug587231.js] skip-if = buildapp == 'mulet' [browser_tabview_bug587276.js] -skip-if = e10s # Bug 1091200 +skip-if = e10s || true # Bug 1091200, bug 1096285 [browser_tabview_bug587351.js] [browser_tabview_bug587503.js] [browser_tabview_bug587990.js] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux32/nightly thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux32/nightly --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux32/nightly 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux32/nightly 2014-11-26 21:45:49.000000000 +0000 @@ -2,7 +2,6 @@ ac_add_options --enable-signmar ac_add_options --enable-profiling -ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux32/valgrind thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux32/valgrind --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux32/valgrind 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux32/valgrind 2014-11-26 21:45:49.000000000 +0000 @@ -5,7 +5,6 @@ ac_add_options --enable-valgrind ac_add_options --disable-jemalloc -ac_add_options --disable-elf-hack ac_add_options --enable-optimize="-g -O -freorder-blocks" ac_add_options --disable-install-strip diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux64/nightly thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux64/nightly --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux64/nightly 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux64/nightly 2014-11-26 21:45:49.000000000 +0000 @@ -2,7 +2,6 @@ ac_add_options --enable-signmar ac_add_options --enable-profiling -ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux64/valgrind thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux64/valgrind --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/linux64/valgrind 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/linux64/valgrind 2014-11-26 21:45:49.000000000 +0000 @@ -5,7 +5,6 @@ ac_add_options --enable-valgrind ac_add_options --disable-jemalloc -ac_add_options --disable-elf-hack ac_add_options --enable-optimize="-g -O -freorder-blocks" ac_add_options --disable-install-strip diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/whitelist thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/whitelist --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/config/mozconfigs/whitelist 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/config/mozconfigs/whitelist 2014-11-26 21:45:49.000000000 +0000 @@ -34,7 +34,6 @@ 'export MOZ_TELEMETRY_REPORTING=1', "mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'", 'STRIP_FLAGS="--strip-debug"', - 'ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling', ] whitelist['nightly']['linux64'] += [ @@ -44,7 +43,6 @@ 'STRIP_FLAGS="--strip-debug"', 'ac_add_options --with-ccache=/usr/bin/ccache', '. "$topsrcdir/build/mozconfig.cache"', - 'ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling', ] whitelist['nightly']['macosx-universal'] += [ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/app-manager/app-projects.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/app-manager/app-projects.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/app-manager/app-projects.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/app-manager/app-projects.js 2014-11-26 21:45:49.000000000 +0000 @@ -16,14 +16,15 @@ const IDB = { _db: null, + databaseName: "AppProjects", open: function () { let deferred = promise.defer(); - let request = indexedDB.open("AppProjects", 5); + let request = indexedDB.open(IDB.databaseName, 5); request.onerror = function(event) { - deferred.reject("Unable to open AppProjects indexedDB. " + - "Error code: " + event.target.errorCode); + deferred.reject("Unable to open AppProjects indexedDB: " + + this.error.name + " - " + this.error.message ); }; request.onupgradeneeded = function(event) { let db = event.target.result; @@ -147,11 +148,10 @@ let loadDeferred = promise.defer(); -IDB.open().then(function (projects) { +loadDeferred.resolve(IDB.open().then(function (projects) { store.object.projects = projects; AppProjects.emit("ready", store.object.projects); - loadDeferred.resolve(); -}); +})); const AppProjects = { load: function() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/debugger-controller.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/debugger-controller.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/debugger-controller.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/debugger-controller.js 2014-11-26 21:45:49.000000000 +0000 @@ -198,14 +198,14 @@ } let target = this._target; - let { client, form: { chromeDebugger, traceActor, addonActor } } = target; + let { client, form: { chromeDebugger, traceActor, actor } } = target; target.on("close", this._onTabDetached); target.on("navigate", this._onTabNavigated); target.on("will-navigate", this._onTabNavigated); this.client = client; - if (addonActor) { - yield this._startAddonDebugging(addonActor); + if (target.isAddon) { + yield this._startAddonDebugging(actor); } else if (target.chrome) { yield this._startChromeDebugging(chromeDebugger); } else { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_aaa_run_first_leaktest.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_aaa_run_first_leaktest.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_aaa_run_first_leaktest.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_aaa_run_first_leaktest.js 2014-11-26 21:45:49.000000000 +0000 @@ -14,15 +14,14 @@ // GC from previous tests does not interfere with the debugger suite. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { ok(aTab, "Should have a tab available."); - ok(aDebuggee, "Should have a debuggee available."); ok(aPanel, "Should have a debugger pane available."); waitForSourceAndCaretAndScopes(aPanel, "-02.js", 1).then(() => { resumeDebuggerThenCloseAndFinish(aPanel); }); - aDebuggee.firstCall(); + callInTab(aTab, "firstCall"); }); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -5,7 +5,7 @@ const TAB_URL = EXAMPLE_URL + "doc_auto-pretty-print-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gPrefs, gOptions, gView; let gFirstSourceLabel = "code_ugly-5.js"; @@ -15,9 +15,8 @@ Services.prefs.setBoolPref("devtools.debugger.auto-pretty-print", true); function test(){ - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -99,7 +98,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breadcrumbs-access.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breadcrumbs-access.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breadcrumbs-access.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breadcrumbs-access.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gFrames; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -28,7 +27,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); function checkNavigationWhileNotFocused() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_break-on-dom-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_break-on-dom-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_break-on-dom-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_break-on-dom-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,7 +8,7 @@ const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let gDebugger = aPanel.panelWin; let gView = gDebugger.DebuggerView; let gEvents = gView.EventListeners; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location2.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location2.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location2.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location2.js 2014-11-26 21:45:49.000000000 +0000 @@ -10,12 +10,11 @@ const TAB_URL = EXAMPLE_URL + "doc_breakpoint-move.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -25,7 +24,7 @@ gBreakpointsRemoving = gBreakpoints._removing; waitForSourceAndCaretAndScopes(gPanel, ".html", 1).then(performTest); - gDebuggee.ermahgerd(); + callInTab(gTab, "ermahgerd"); }); function performTest() { @@ -62,7 +61,7 @@ yield resumeAndTestBreakpoint(20); yield doResume(gPanel); - executeSoon(() => gDebuggee.ermahgerd()); + callInTab(gTab, "ermahgerd"); yield waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES); yield resumeAndTestBreakpoint(20); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-actual-location.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,12 +9,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -24,7 +23,7 @@ gBreakpointsRemoving = gBreakpoints._removing; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); function performTest() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js 2014-11-26 21:45:49.000000000 +0000 @@ -15,7 +15,7 @@ let gPanel, gDebugger, gThreadClient, gEvents; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gPanel = aPanel; gDebugger = gPanel.panelWin; gThreadClient = gDebugger.gThreadClient; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gBreakpoints; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-button-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,12 +9,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gBreakpoints; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu-add.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu-add.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu-add.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu-add.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources, gContextMenu, gBreakpoints, gBreakpointsAdded; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -29,7 +28,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); function performTest() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js 2014-11-26 21:45:49.000000000 +0000 @@ -11,12 +11,11 @@ // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gBreakpoints; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -95,13 +94,7 @@ ok(isCaretPos(gPanel, 9), "The editor location is correct before pausing."); - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return finished; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-disabled-reload.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-disabled-reload.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-disabled-reload.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-disabled-reload.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,7 +8,8 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { + let gTab = aTab; let gDebugger = aPanel.panelWin; let gEvents = gDebugger.EVENTS; let gEditor = gDebugger.DebuggerView.editor; @@ -66,7 +67,7 @@ yield ensureSourceIs(aPanel, "-01.js"); yield verifyView({ disabled: false, visible: true }); - executeSoon(() => aDebuggee.firstCall()); + callInTab(gTab, "firstCall"); yield waitForDebuggerEvents(aPanel, gEvents.FETCHED_SCOPES); yield ensureSourceIs(aPanel, "-01.js"); yield ensureCaretAt(aPanel, 5); @@ -83,7 +84,7 @@ yield ensureSourceIs(aPanel, "-02.js", true); yield verifyView({ disabled: false, visible: false }); - executeSoon(() => aDebuggee.firstCall()); + callInTab(gTab, "firstCall"); yield waitForSourceAndCaretAndScopes(aPanel, "-01.js", 1); yield verifyView({ disabled: false, visible: true }); @@ -98,7 +99,7 @@ yield ensureSourceIs(aPanel, "-02.js", true); yield verifyView({ disabled: true, visible: false }); - executeSoon(() => aDebuggee.firstCall()); + callInTab(gTab, "firstCall"); yield waitForDebuggerEvents(aPanel, gEvents.FETCHED_SCOPES); yield ensureSourceIs(aPanel, "-02.js"); yield ensureCaretAt(aPanel, 1); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-editor.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-editor.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-editor.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-editor.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,12 +9,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -24,7 +23,7 @@ gBreakpointsRemoving = gBreakpoints._removing; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); function performTest() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-highlight.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-highlight.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-highlight.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-highlight.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-new-script.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-new-script.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-new-script.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-new-script.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_inline-script.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -33,7 +32,7 @@ }); }); - gDebuggee.runDebuggerStatement(); + callInTab(gTab, "runDebuggerStatement"); } function testResume() { @@ -54,9 +53,7 @@ }); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -84,7 +81,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-other-tabs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-other-tabs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-other-tabs.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-other-tabs.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,8 +9,8 @@ const TAB_URL = EXAMPLE_URL + "doc_breakpoints-other-tabs.html"; let test = Task.async(function* () { - const [tab1, debuggee1, panel1] = yield initDebugger(TAB_URL); - const [tab2, debuggee2, panel2] = yield initDebugger(TAB_URL); + const [tab1,, panel1] = yield initDebugger(TAB_URL); + const [tab2,, panel2] = yield initDebugger(TAB_URL); yield ensureSourceIs(panel1, "code_breakpoints-other-tabs.js", true); @@ -22,7 +22,7 @@ }); const paused = waitForThreadEvents(panel2, "paused"); - executeSoon(() => debuggee2.testCase()); + callInTab(tab2, "testCase"); const packet = yield paused; is(packet.why.type, "debuggerStatement", diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-pane.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-pane.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-pane.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-pane.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,12 +9,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -24,7 +23,7 @@ gBreakpointsRemoving = gBreakpoints._removing; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); let breakpointsAdded = 0; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-reload.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-reload.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-reload.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_breakpoints-reload.js 2014-11-26 21:45:49.000000000 +0000 @@ -11,7 +11,7 @@ let test = Task.async(function* () { requestLongerTimeout(4); - const [tab, debuggee, panel] = yield initDebugger(TAB_URL); + const [tab,, panel] = yield initDebugger(TAB_URL); yield ensureSourceIs(panel, "doc_breakpoints-reload.html", true); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_clean-exit.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_clean-exit.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_clean-exit.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_clean-exit.js 2014-11-26 21:45:49.000000000 +0000 @@ -5,14 +5,13 @@ * Test that closing a tab with the debugger in a paused state exits cleanly. */ -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -28,12 +27,11 @@ return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_REFILLED); }).then(() => closeDebuggerAndFinish(gPanel, { whilePaused: true })); - gDebuggee.runDebuggerStatement(); + callInTab(gTab, "runDebuggerStatement"); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_closure-inspection.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_closure-inspection.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_closure-inspection.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_closure-inspection.js 2014-11-26 21:45:49.000000000 +0000 @@ -6,14 +6,12 @@ // Test that inspecting a closure works as expected. function test() { - let gPanel, gTab, gDebuggee, gDebugger; + let gPanel, gTab, gDebugger; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; - gDebuggee.gRecurseLimit = 2; waitForSourceShown(gPanel, ".html") .then(testClosure) @@ -24,13 +22,7 @@ }); function testClosure() { - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => { let gVars = gDebugger.DebuggerView.Variables; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,7 +9,7 @@ function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let frames = win.DebuggerController.StackFrames; let framesView = win.DebuggerView.StackFrames; @@ -45,8 +45,7 @@ "Evaluating shouldn't work while the debuggee isn't paused."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.firstCall()); + callInTab(tab, "firstCall"); yield waitForSourceAndCaretAndScopes(panel, "-02.js", 1); checkView(0, 1, 1, [/secondCall/, 118]); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_controller-evaluate-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,7 +9,7 @@ function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let frames = win.DebuggerController.StackFrames; let framesView = win.DebuggerView.StackFrames; @@ -38,7 +38,7 @@ is(sources._cache.size, 2, "There should be two cached sources in the cache."); // Allow this generator function to yield first. - executeSoon(() => debuggee.firstCall()); + callInTab(tab, "firstCall"); yield waitForSourceAndCaretAndScopes(panel, "-02.js", 1); checkView(0, 1, 1, [/secondCall/, 118]); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_debugger-statement.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_debugger-statement.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_debugger-statement.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_debugger-statement.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,6 +8,7 @@ const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html"; let gClient; +let gTab; function test() { if (!DebuggerServer.initialized) { @@ -22,7 +23,10 @@ "Root actor should identify itself as a browser."); addTab(TAB_URL) - .then(() => attachTabActorForUrl(gClient, TAB_URL)) + .then((aTab) => { + gTab = aTab; + return attachTabActorForUrl(gClient, TAB_URL) + }) .then(testEarlyDebuggerStatement) .then(testDebuggerStatement) .then(closeConnection) @@ -45,8 +49,7 @@ // This should continue without nesting an event loop and calling // the onPaused hook, because we haven't attached yet. - let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject; - debuggee.runDebuggerStatement(); + callInTab(gTab, "runDebuggerStatement"); gClient.removeListener("paused", onPaused); @@ -72,8 +75,7 @@ }); // Reach around the debugging protocol and execute the debugger statement. - let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject; - debuggee.runDebuggerStatement(); + callInTab(gTab, "runDebuggerStatement"); } function closeConnection() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_editor-contextmenu.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_editor-contextmenu.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_editor-contextmenu.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_editor-contextmenu.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gSources, gContextMenu; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -21,7 +20,7 @@ gContextMenu = gDebugger.document.getElementById("sourceEditorContextMenu"); waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest).then(null, info); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); function performTest() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_editor-mode.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_editor-mode.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_editor-mode.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_editor-mode.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -29,7 +28,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -85,7 +84,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,6 +8,7 @@ const TAB_URL = EXAMPLE_URL + "doc_event-listeners-01.html"; let gClient; +let gTab; function test() { if (!DebuggerServer.initialized) { @@ -22,7 +23,10 @@ "Root actor should identify itself as a browser."); addTab(TAB_URL) - .then(() => attachThreadActorForUrl(gClient, TAB_URL)) + .then((aTab) => { + gTab = aTab; + return attachThreadActorForUrl(gClient, TAB_URL) + }) .then(pauseDebuggee) .then(testEventListeners) .then(closeConnection) @@ -45,13 +49,7 @@ deferred.resolve(aThreadClient); }); - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - content.document.querySelector("button"), - content); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return deferred.promise; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,6 +9,7 @@ const TAB_URL = EXAMPLE_URL + "doc_event-listeners-03.html"; let gClient; +let gTab; function test() { if (!DebuggerServer.initialized) { @@ -23,7 +24,10 @@ "Root actor should identify itself as a browser."); addTab(TAB_URL) - .then(() => attachThreadActorForUrl(gClient, TAB_URL)) + .then((aTab) => { + gTab = aTab; + return attachThreadActorForUrl(gClient, TAB_URL); + }) .then(pauseDebuggee) .then(testEventListeners) .then(closeConnection) @@ -46,13 +50,7 @@ deferred.resolve(aThreadClient); }); - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - content.document.querySelector("button"), - content); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return deferred.promise; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_event-listeners-03.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,6 +9,7 @@ const TAB_URL = EXAMPLE_URL + "doc_native-event-handler.html"; let gClient; +let gTab; function test() { if (!DebuggerServer.initialized) { @@ -23,7 +24,10 @@ "Root actor should identify itself as a browser."); addTab(TAB_URL) - .then(() => attachThreadActorForUrl(gClient, TAB_URL)) + .then((aTab) => { + gTab = aTab; + return attachThreadActorForUrl(gClient, TAB_URL) + }) .then(pauseDebuggee) .then(testEventListeners) .then(closeConnection) @@ -46,13 +50,7 @@ deferred.resolve(aThreadClient); }); - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - content.document.querySelector("button"), - content); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return deferred.promise; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_file-reload.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_file-reload.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_file-reload.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_file-reload.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,7 +9,7 @@ const JS_URL = EXAMPLE_URL + "sjs_random-javascript.sjs"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let gDebugger = aPanel.panelWin; let gEditor = gDebugger.DebuggerView.editor; let gSources = gDebugger.DebuggerView.Sources; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_function-display-name.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_function-display-name.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_function-display-name.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_function-display-name.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_function-display-name.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -35,7 +34,7 @@ testInferredName(); }); - gDebuggee.evalCall(); + callInTab(gTab, "evalCall"); } function testInferredName() { @@ -57,7 +56,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_global-method-override.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_global-method-override.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_global-method-override.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_global-method-override.js 2014-11-26 21:45:49.000000000 +0000 @@ -10,7 +10,7 @@ const TAB_URL = EXAMPLE_URL + "doc_global-method-override.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let gDebugger = aPanel.panelWin; ok(gDebugger, "Should have a debugger available."); is(gDebugger.gThreadClient.state, "attached", "Debugger should be attached."); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,16 +9,15 @@ const TAB_URL = EXAMPLE_URL + "doc_same-line-functions.html"; const CODE_URL = "code_same-line-functions.js"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor; function test() { Task.async(function* () { yield pushPrefs(["devtools.debugger.tracer", true]); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -44,9 +43,7 @@ } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function testHitCounts() { @@ -58,8 +55,7 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; -}); \ No newline at end of file +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_same-line-functions.html"; const CODE_URL = "code_same-line-functions.js"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor; function test() { Task.async(function* () { yield pushPrefs(["devtools.debugger.tracer", true]); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -46,9 +45,7 @@ } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function testHitCountsBeforeStopping() { @@ -63,8 +60,7 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; -}); \ No newline at end of file +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_host-layout.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_host-layout.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_host-layout.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_host-layout.js 2014-11-26 21:45:49.000000000 +0000 @@ -27,14 +27,14 @@ return Task.spawn(function() { let [tab, debuggee, panel] = yield initDebugger("about:blank"); - yield testHost(tab, debuggee, panel, firstHost, firstLayout); - yield switchAndTestHost(tab, debuggee, panel, secondHost, secondLayout); - yield switchAndTestHost(tab, debuggee, panel, thirdHost, thirdLayout); + yield testHost(tab, panel, firstHost, firstLayout); + yield switchAndTestHost(tab, panel, secondHost, secondLayout); + yield switchAndTestHost(tab, panel, thirdHost, thirdLayout); yield teardown(panel); }); } -function switchAndTestHost(aTab, aDebuggee, aPanel, aHostType, aLayoutType) { +function switchAndTestHost(aTab, aPanel, aHostType, aLayoutType) { let gToolbox = aPanel._toolbox; let gDebugger = aPanel.panelWin; @@ -48,7 +48,7 @@ yield layoutChanged; ok(true, "The debugger's layout has changed."); - yield testHost(aTab, aDebuggee, aPanel, aHostType, aLayoutType); + yield testHost(aTab, aPanel, aHostType, aLayoutType); }); function once(aTarget, aEvent) { @@ -58,7 +58,7 @@ } } -function testHost(aTab, aDebuggee, aPanel, aHostType, aLayoutType) { +function testHost(aTab, aPanel, aHostType, aLayoutType) { let gDebugger = aPanel.panelWin; let gView = gDebugger.DebuggerView; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_instruments-pane-collapse.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_instruments-pane-collapse.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_instruments-pane-collapse.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_instruments-pane-collapse.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gPrefs, gOptions; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gPrefs = gDebugger.Prefs; @@ -146,7 +145,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gPrefs = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_interrupts.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_interrupts.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_interrupts.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_interrupts.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gBreakpoints, gTarget, gResumeButton, gResumeKey, gThreadClient; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-01-simple.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-01-simple.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-01-simple.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-01-simple.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -21,7 +20,7 @@ gFrames = gDebugger.DebuggerView.StackFrames; waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(performTest); - gDebuggee.simpleCall(); + callInTab(gTab, "simpleCall"); }); } @@ -62,7 +61,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-02-blank.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-02-blank.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-02-blank.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_location-changes-02-blank.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -21,7 +20,7 @@ gFrames = gDebugger.DebuggerView.StackFrames; waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(testLocationChange); - gDebuggee.simpleCall(); + callInTab(gTab, "simpleCall"); }); } @@ -53,7 +52,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-highlight.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-highlight.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-highlight.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-highlight.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gToolbox, gToolboxTab; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gToolbox = gPanel._toolbox; @@ -69,7 +68,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gToolbox = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-raise.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-raise.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-raise.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_on-pause-raise.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gNewTab, gFocusedWindow, gToolbox, gToolboxTab; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gToolbox = gPanel._toolbox; @@ -132,7 +131,6 @@ Services.prefs.setCharPref("devtools.toolbox.host", devtools.Toolbox.HostType.BOTTOM); gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_optimized-out-vars.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_optimized-out-vars.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_optimized-out-vars.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_optimized-out-vars.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,7 +8,7 @@ const TAB_URL = EXAMPLE_URL + "doc_closure-optimized-out.html"; let gDebugger, sources; - let [, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); gDebugger = panel.panelWin; sources = gDebugger.DebuggerView.Sources; @@ -18,11 +18,7 @@ // Spin the event loop before causing the debuggee to pause, to allow // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - debuggee.document.querySelector("button"), - debuggee); - }); + sendMouseClickToTab(tab, content.document.querySelector("button")); yield waitForDebuggerEvents(panel, gDebugger.EVENTS.FETCHED_SCOPES); let gVars = gDebugger.DebuggerView.Variables; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_panel-size.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_panel-size.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_panel-size.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_panel-size.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,12 +9,11 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gPrefs, gSources, gInstruments; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gPrefs = gDebugger.Prefs; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,14 +7,13 @@ const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gFrames, gVariables, gPrefs, gOptions; function test() { requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gFrames = gDebugger.DebuggerView.StackFrames; @@ -78,9 +77,7 @@ return finished; }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return finished; } @@ -151,9 +148,7 @@ return finished; }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return finished; } @@ -236,7 +231,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gFrames = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-exceptions-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gFrames, gVariables, gPrefs, gOptions; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gFrames = gDebugger.DebuggerView.StackFrames; @@ -105,13 +104,7 @@ return finished; }); - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee.window); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); return finished; } @@ -194,7 +187,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gFrames = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-resume.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-resume.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-resume.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-resume.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gResumeButton, gResumeKey, gFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gResumeButton = gDebugger.document.getElementById("resume"); @@ -69,7 +68,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gResumeButton = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-warning.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-warning.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_pause-warning.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_pause-warning.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_inline-script.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gTarget, gToolbox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gTarget = gPanel.target; @@ -90,7 +89,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gTarget = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_progress-listener-bug.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_progress-listener-bug.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_progress-listener-bug.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_progress-listener-bug.js 2014-11-26 21:45:49.000000000 +0000 @@ -6,7 +6,7 @@ * WebProgress argument's DOMWindow property in onStateChange() (bug 771655). */ -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gOldListener; const TAB_URL = EXAMPLE_URL + "doc_inline-script.html"; @@ -14,9 +14,8 @@ function test() { installListener(); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -37,7 +36,7 @@ resumeDebuggerThenCloseAndFinish(gPanel); }); - gDebuggee.runDebuggerStatement(); + callInTab(gTab, "runDebuggerStatement"); } // This is taken almost verbatim from bug 771655. @@ -80,7 +79,6 @@ } gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gOldListener = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,13 +9,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; const PREFERRED_URL = EXAMPLE_URL + "code_script-switching-02.js"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -39,7 +38,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_reload-preferred-script-03.js 2014-11-26 21:45:49.000000000 +0000 @@ -10,13 +10,12 @@ const FIRST_URL = EXAMPLE_URL + "code_script-switching-01.js"; const SECOND_URL = EXAMPLE_URL + "code_script-switching-02.js"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -52,7 +51,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_reload-same-script.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_reload-same-script.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_reload-same-script.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_reload-same-script.js 2014-11-26 21:45:49.000000000 +0000 @@ -13,12 +13,11 @@ // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gStep; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = aPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -32,7 +31,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -187,7 +186,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-02.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -29,7 +28,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -176,7 +175,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_scripts-switching-03.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gView, gEditor, gL10N; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gView = gDebugger.DebuggerView; @@ -43,7 +42,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gView = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-autofill-identifier.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-autofill-identifier.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-autofill-identifier.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-autofill-identifier.js 2014-11-26 21:45:49.000000000 +0000 @@ -10,7 +10,7 @@ function test() { const TAB_URL = EXAMPLE_URL + "doc_function-search.html"; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let Source = 'code_function-search-01.js'; let Debugger = aPanel.panelWin; let Editor = Debugger.DebuggerView.editor; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFiltering, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -309,7 +308,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -33,7 +32,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -116,7 +115,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-03.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -37,7 +36,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -112,7 +111,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-04.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-04.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-04.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-basic-04.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -123,7 +122,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSearchBox, gSearchBoxPanel; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; @@ -28,7 +27,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -52,7 +51,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSearchBox = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSearchBox, gSearchBoxPanel; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -34,7 +33,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -77,7 +76,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-parse.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-parse.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-parse.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_searchbox-parse.js 2014-11-26 21:45:49.000000000 +0000 @@ -6,7 +6,7 @@ */ function test() { - initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => { + initDebugger("about:blank").then(([aTab,, aPanel]) => { let filterView = aPanel.panelWin.DebuggerView.Filtering; let searchbox = aPanel.panelWin.DebuggerView.Filtering._searchbox; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -31,7 +30,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -264,7 +263,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -34,7 +33,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -208,7 +207,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-03.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -30,7 +29,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -96,7 +95,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-04.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-04.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-04.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-04.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -30,7 +29,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -84,7 +83,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-05.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-05.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-05.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-05.js 2014-11-26 21:45:49.000000000 +0000 @@ -9,13 +9,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -33,7 +32,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -146,7 +145,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-06.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-06.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-06.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-global-06.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -32,7 +31,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -111,7 +110,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; @@ -111,7 +110,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSearchBox = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,16 +7,15 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchView, gSearchBox; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(3); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -226,7 +225,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,16 +7,15 @@ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSourceUtils, gSearchView, gSearchBox; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(3); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -268,7 +267,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-sources-03.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -92,7 +91,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-symbols.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-symbols.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_search-symbols.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_search-symbols.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_function-search.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchBox, gFilteredFunctions; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -459,7 +458,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_sources-labels.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_sources-labels.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_sources-labels.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_sources-labels.js 2014-11-26 21:45:49.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gSources, gUtils; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_sources-sorting.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_sources-sorting.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_sources-sorting.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_sources-sorting.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gUtils; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; @@ -129,7 +128,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-01.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,20 +7,19 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gFrames, gClassicFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gFrames = gDebugger.DebuggerView.StackFrames; gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList; waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(performTest); - gDebuggee.simpleCall(); + callInTab(gTab, "simpleCall"); }); } @@ -37,7 +36,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gFrames = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-02.js 2014-11-26 21:45:49.000000000 +0000 @@ -7,20 +7,19 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gFrames, gClassicFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gFrames = gDebugger.DebuggerView.StackFrames; gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList; waitForSourceAndCaretAndScopes(gPanel, ".html", 1).then(performTest); - gDebuggee.evalCall(); + callInTab(gTab, "evalCall"); }); } @@ -103,7 +102,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gFrames = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-04.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-04.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-04.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-04.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,20 +7,19 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gFrames, gClassicFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gFrames = gDebugger.DebuggerView.StackFrames; gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList; waitForSourceAndCaretAndScopes(gPanel, ".html", 1).then(performTest); - gDebuggee.evalCall(); + callInTab(gTab, "evalCall"); }); } @@ -46,7 +45,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gFrames = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-05.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-05.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-05.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-05.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFrames, gClassicFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -32,7 +31,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -158,7 +157,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-06.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-06.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-06.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-06.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFrames, gClassicFrames; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -23,7 +22,7 @@ gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -78,7 +77,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-07.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-07.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_stack-07.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_stack-07.js 2014-11-26 21:45:50.000000000 +0000 @@ -9,13 +9,12 @@ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFrames, gClassicFrames, gToolbar; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; @@ -25,7 +24,7 @@ gToolbar = gDebugger.DebuggerView.Toolbar; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } @@ -98,7 +97,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_step-out.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_step-out.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_step-out.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_step-out.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_step-out.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVars; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVars = gDebugger.DebuggerView.Variables; @@ -41,9 +40,7 @@ gDebugger); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.getElementById("return"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.getElementById("return")); } function testReturnWithException() { @@ -65,9 +62,7 @@ gDebugger); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.getElementById("throw"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.getElementById("throw")); } function resumeDebuggee() { @@ -78,7 +73,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVars = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_terminate-on-tab-close.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_terminate-on-tab-close.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_terminate-on-tab-close.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_terminate-on-tab-close.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,12 +7,11 @@ const TAB_URL = EXAMPLE_URL + "doc_terminate-on-tab-close.html"; -let gTab, gDebuggee, gDebugger, gPanel; +let gTab, gDebugger, gPanel; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -27,12 +26,11 @@ }); }); - gDebuggee.debuggerThenThrow(); + callInTab(gTab, "debuggerThenThrow"); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-accessibility.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-accessibility.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-accessibility.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-accessibility.js 2014-11-26 21:45:50.000000000 +0000 @@ -5,13 +5,12 @@ * Make sure that the variables view is keyboard accessible. */ -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariablesView; function test() { - initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => { + initDebugger("about:blank").then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariablesView = gDebugger.DebuggerView.Variables; @@ -504,7 +503,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariablesView = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-data.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-data.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-data.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-data.js 2014-11-26 21:45:50.000000000 +0000 @@ -6,13 +6,12 @@ * when given some raw data. */ -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariablesView, gScope, gVariable; function test() { - initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => { + initDebugger("about:blank").then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariablesView = gDebugger.DebuggerView.Variables; @@ -602,7 +601,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariablesView = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-cancel.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-cancel.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-cancel.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-cancel.js 2014-11-26 21:45:50.000000000 +0000 @@ -10,14 +10,13 @@ function test() { Task.spawn(function*() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let vars = win.DebuggerView.Variables; win.DebuggerView.WatchExpressions.addExpression("this"); - // Allow this generator function to yield first. - executeSoon(() => debuggee.ermahgerd()); + callInTab(tab, "ermahgerd"); yield waitForDebuggerEvents(panel, win.EVENTS.FETCHED_WATCH_EXPRESSIONS); let exprScope = vars.getScopeAtIndex(0); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-01.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,16 +7,15 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gL10N, gEditor, gVars, gWatch; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gL10N = gDebugger.L10N; @@ -115,9 +114,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -288,7 +285,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gL10N = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gL10N, gEditor, gVars, gWatch; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gL10N = gDebugger.L10N; @@ -36,9 +35,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -94,7 +91,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gL10N = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-value.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-value.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-value.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-value.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVars; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVars = gDebugger.DebuggerView.Variables; @@ -38,9 +37,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -82,7 +79,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVars = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-watch.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-watch.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-watch.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-edit-watch.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_watch-expressions.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gL10N, gEditor, gVars, gWatch; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gL10N = gDebugger.L10N; @@ -44,7 +43,7 @@ }); addExpressions(); - gDebuggee.ermahgerd(); + callInTab(gTab, "ermahgerd"); }); } @@ -494,7 +493,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gL10N = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-pref.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-pref.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-pref.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-pref.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_with-frame.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gPrefs, gOptions, gVariables; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gPrefs = gDebugger.Prefs; @@ -72,7 +71,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gPrefs = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-searchbox.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-searchbox.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-searchbox.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-filter-searchbox.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_with-frame.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -139,7 +138,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-01.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -30,9 +29,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -253,7 +250,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-02.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -35,9 +34,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -543,7 +540,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-03.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -32,9 +31,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -148,7 +145,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_with-frame.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -34,9 +33,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -204,7 +201,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frozen-sealed-nonext.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frozen-sealed-nonext.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frozen-sealed-nonext.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-frozen-sealed-nonext.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,12 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -24,7 +23,7 @@ function prepareTest() { gDebugger.once(gDebugger.EVENTS.FETCHED_SCOPES, runTest); - gDebuggee.eval("(" + function() { + evalInTab(gTab, "(" + function() { var frozen = Object.freeze({}); var sealed = Object.seal({}); var nonExtensible = Object.preventExtensions({}); @@ -83,7 +82,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-hide-non-enums.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-hide-non-enums.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-hide-non-enums.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-hide-non-enums.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,17 +8,16 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(performTest); - gDebuggee.simpleCall(); + callInTab(gTab, "simpleCall"); }); } @@ -101,7 +100,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-large-array-buffer.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-large-array-buffer.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-large-array-buffer.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-large-array-buffer.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,13 +8,12 @@ const TAB_URL = EXAMPLE_URL + "doc_large-array-buffer.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables, gEllipsis; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -29,9 +28,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -235,7 +232,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-01.js 2014-11-26 21:45:50.000000000 +0000 @@ -10,13 +10,12 @@ function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let variables = win.DebuggerView.Variables; - // Allow this generator function to yield first. - executeSoon(() => debuggee.test()); + callInTab(tab, "test"); yield waitForSourceAndCaretAndScopes(panel, ".html", 23); let firstScope = variables.getScopeAtIndex(0); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-override-02.js 2014-11-26 21:45:50.000000000 +0000 @@ -9,7 +9,7 @@ function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let variables = win.DebuggerView.Variables; @@ -18,8 +18,7 @@ let committedLocalScopeHierarchy = promise.defer(); variables.oncommit = committedLocalScopeHierarchy.resolve; - // Allow this generator function to yield first. - executeSoon(() => debuggee.test()); + callInTab(tab, "test"); yield waitForSourceAndCaretAndScopes(panel, ".html", 23); yield committedLocalScopeHierarchy.promise; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-01.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,16 +7,15 @@ const TAB_URL = EXAMPLE_URL + "doc_with-frame.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gBreakpoints, gSources, gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(4); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gBreakpoints = gDebugger.DebuggerController.Breakpoints; @@ -45,13 +44,7 @@ } function pauseDebuggee() { - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); // The first 'with' scope should be expanded by default, but the // variables haven't been fetched yet. This is how 'with' scopes work. @@ -200,7 +193,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gBreakpoints = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-02.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_with-frame.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gBreakpoints, gSources, gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(4); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gBreakpoints = gDebugger.DebuggerController.Breakpoints; @@ -46,13 +45,7 @@ } function pauseDebuggee() { - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); - }); + sendMouseClickToTab(gTab, content.document.querySelector("button")); // The first 'with' scope should be expanded by default, but the // variables haven't been fetched yet. This is how 'with' scopes work. @@ -215,7 +208,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gBreakpoints = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-03.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-reexpand-03.js 2014-11-26 21:45:50.000000000 +0000 @@ -7,16 +7,15 @@ const TAB_URL = EXAMPLE_URL + "doc_scope-variable-4.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gBreakpoints, gSources, gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(4); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gBreakpoints = gDebugger.DebuggerController.Breakpoints; @@ -45,11 +44,7 @@ } function pauseDebuggee() { - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - gDebuggee.test(); - }); + callInTab(gTab, "test"); return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES); } @@ -120,7 +115,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gBreakpoints = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-webidl.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-webidl.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-webidl.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_variables-view-webidl.js 2014-11-26 21:45:50.000000000 +0000 @@ -8,16 +8,15 @@ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; @@ -30,9 +29,7 @@ ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); }); } @@ -253,7 +250,6 @@ registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gVariables = null; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-01.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-01.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-01.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-01.js 2014-11-26 21:45:50.000000000 +0000 @@ -11,12 +11,11 @@ // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gEditor, gWatch, gVariables; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-02.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser_dbg_watch-expressions-02.js 2014-11-26 21:45:50.000000000 +0000 @@ -11,12 +11,11 @@ // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - let gTab, gDebuggee, gPanel, gDebugger; + let gTab, gPanel, gDebugger; let gWatch, gVariables; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gWatch = gDebugger.DebuggerView.WatchExpressions; @@ -113,7 +112,7 @@ aCallback(); }); - gDebuggee.test(); + callInTab(gTab, "test"); } function test2(aCallback) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/browser.ini 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/browser.ini 2014-11-26 21:45:49.000000000 +0000 @@ -98,25 +98,25 @@ testactors.js [browser_dbg_aaa_run_first_leaktest.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_addonactor.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_addon-sources.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_addon-modules.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_addon-modules-unpacked.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_addon-panels.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_addon-console.js] -skip-if = e10s || os == 'win' # bug 1005274 +skip-if = e10s && debug || os == 'win' # bug 1005274 [browser_dbg_auto-pretty-print-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_auto-pretty-print-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_bfcache.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_blackboxing-01.js] skip-if = e10s && debug [browser_dbg_blackboxing-02.js] @@ -130,9 +130,9 @@ [browser_dbg_blackboxing-06.js] skip-if = e10s && debug [browser_dbg_breadcrumbs-access.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_break-on-dom-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_break-on-dom-02.js] skip-if = e10s && debug [browser_dbg_break-on-dom-03.js] @@ -150,51 +150,51 @@ [browser_dbg_break-on-dom-event-01.js] skip-if = e10s || os == "mac" || e10s # Bug 895426 [browser_dbg_break-on-dom-event-02.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_breakpoints-actual-location.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-actual-location2.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js] -skip-if = e10s +skip-if = e10s # Bug 1093535 [browser_dbg_breakpoints-button-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-button-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-contextmenu-add.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-contextmenu.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-disabled-reload.js] -skip-if = e10s +skip-if = e10s # Bug 1093535 [browser_dbg_breakpoints-editor.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-highlight.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-new-script.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-other-tabs.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-pane.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_breakpoints-reload.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_chrome-create.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_chrome-debugging.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_clean-exit-window.js] skip-if = true # Bug 933950 (leaky test) [browser_dbg_clean-exit.js] skip-if = true # Bug 1044985 (racy test) [browser_dbg_closure-inspection.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_cmd-blackbox.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_cmd-break.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_cmd-dbg.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_conditional-breakpoints-01.js] skip-if = e10s && debug [browser_dbg_conditional-breakpoints-02.js] @@ -212,73 +212,73 @@ [browser_dbg_server-conditional-bp-04.js] skip-if = e10s && debug [browser_dbg_controller-evaluate-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_controller-evaluate-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_debugger-statement.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_editor-contextmenu.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_editor-mode.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_event-listeners-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_event-listeners-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_event-listeners-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_file-reload.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_function-display-name.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_global-method-override.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_globalactor.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_hide-toolbar-buttons.js] skip-if = e10s [browser_dbg_hit-counts-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_hit-counts-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_host-layout.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_iframes.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_instruments-pane-collapse.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_interrupts.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_listaddons.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_listtabs-01.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_listtabs-02.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_listtabs-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_location-changes-01-simple.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_location-changes-02-blank.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_location-changes-03-new.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_location-changes-04-breakpoint.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_multiple-windows.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_navigation.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_no-page-sources.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_on-pause-highlight.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_on-pause-raise.js] -skip-if = e10s || os == "linux" || e10s # Bug 888811 & bug 891176 +skip-if = e10s && debug || os == "linux" # Bug 888811 & bug 891176 [browser_dbg_optimized-out-vars.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_panel-size.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_parser-01.js] skip-if = e10s && debug [browser_dbg_parser-02.js] @@ -300,13 +300,13 @@ [browser_dbg_parser-10.js] skip-if = e10s && debug [browser_dbg_pause-exceptions-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_pause-exceptions-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_pause-resume.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_pause-warning.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_paused-keybindings.js] skip-if = e10s [browser_dbg_pretty-print-01.js] @@ -338,59 +338,59 @@ [browser_dbg_pretty-print-on-paused.js] skip-if = e10s && debug [browser_dbg_progress-listener-bug.js] -skip-if = e10s +skip-if = e10a && debug [browser_dbg_reload-preferred-script-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_reload-preferred-script-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_reload-preferred-script-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_reload-same-script.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_scripts-switching-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_scripts-switching-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_scripts-switching-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-autofill-identifier.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-03.js] -skip-if = e10s +skip-if = e10s # Bug 1093535 [browser_dbg_search-global-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-05.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-06.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-popup-jank.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-sources-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-sources-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-sources-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-symbols.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_searchbox-help-popup-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_searchbox-help-popup-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_searchbox-parse.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_source-maps-01.js] skip-if = e10s && debug [browser_dbg_source-maps-02.js] @@ -400,35 +400,35 @@ [browser_dbg_source-maps-04.js] skip-if = e10s # Bug 1093535 [browser_dbg_sources-cache.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_sources-labels.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_sources-sorting.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_split-console-paused-reload.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_stack-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_stack-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_stack-03.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_stack-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_stack-05.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_stack-06.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_stack-07.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_step-out.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tabactor-01.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_tabactor-02.js] -skip-if = e10s +skip-if = e10s # TODO [browser_dbg_terminate-on-tab-close.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-01.js] skip-if = e10s && debug [browser_dbg_tracing-02.js] @@ -458,21 +458,21 @@ [browser_dbg_variables-view-06.js] skip-if = e10s && debug [browser_dbg_variables-view-accessibility.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-data.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-edit-cancel.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-edit-click.js] skip-if = e10s || (os == 'mac' || os == 'win') && (debug == false) # Bug 986166 [browser_dbg_variables-view-edit-getset-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-edit-getset-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-edit-value.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-edit-watch.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-filter-01.js] skip-if = e10s && debug [browser_dbg_variables-view-filter-02.js] @@ -484,27 +484,27 @@ [browser_dbg_variables-view-filter-05.js] skip-if = e10s && debug [browser_dbg_variables-view-filter-pref.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-filter-searchbox.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-frame-parameters-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-frame-parameters-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-frame-parameters-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-frame-with.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-frozen-sealed-nonext.js] -skip-if = e10s || buildapp == 'mulet' +skip-if = e10s && debug || buildapp == 'mulet' [browser_dbg_variables-view-hide-non-enums.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-large-array-buffer.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-override-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-override-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-01.js] skip-if = e10s && debug [browser_dbg_variables-view-popup-02.js] @@ -532,20 +532,20 @@ [browser_dbg_variables-view-popup-13.js] skip-if = e10s && debug [browser_dbg_variables-view-popup-14.js] -skip-if = e10s && debug +skip-if = (e10s && debug) || (e10s && os == 'linux') # Linux e10s - bug 1029545 [browser_dbg_variables-view-popup-15.js] skip-if = e10s && debug [browser_dbg_variables-view-popup-16.js] skip-if = e10s && debug [browser_dbg_variables-view-reexpand-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-reexpand-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-reexpand-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-webidl.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_watch-expressions-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_watch-expressions-02.js] -skip-if = e10s +skip-if = e10s && debug diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/code_frame-script.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/code_frame-script.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/code_frame-script.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/code_frame-script.js 2014-11-26 21:45:50.000000000 +0000 @@ -24,3 +24,10 @@ EventUtils.synthesizeMouseAtCenter(target, {}, target.ownerDocument.defaultView); }); + +addMessageListener("test:eval", function (message) { + dump("Evalling string " + message.data.string + ".\n"); + + content.eval(message.data.string); + sendAsyncMessage("test:eval"); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/head.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/head.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/debugger/test/head.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/debugger/test/head.js 2014-11-26 21:45:50.000000000 +0000 @@ -567,11 +567,7 @@ let addonActor = yield getAddonActorForUrl(this.client, aUrl); let targetOptions = { - form: { - addonActor: addonActor.actor, - consoleActor: addonActor.consoleActor, - title: addonActor.name - }, + form: addonActor, client: this.client, chrome: true }; @@ -970,6 +966,15 @@ waitForMessageFromTab(tab, "test:call"); } +function evalInTab(tab, string) { + info("Evalling string " + string + " in tab."); + + sendMessageToTab(tab, "test:eval", { + string: string, + }); + waitForMessageFromTab(tab, "test:eval"); +} + function sendMouseClickToTab(tab, target) { info("Sending mouse click to tab."); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/connect/connect.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/connect/connect.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/connect/connect.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/connect/connect.js 2014-11-26 21:45:50.000000000 +0000 @@ -154,7 +154,7 @@ function buildAddonLink(addon, parent) { let a = document.createElement("a"); a.onclick = function() { - openToolbox({ addonActor: addon.actor, title: addon.name }, true, "jsdebugger"); + openToolbox(addon, true, "jsdebugger"); } a.textContent = addon.name; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/gDevTools.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/gDevTools.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/gDevTools.jsm 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/gDevTools.jsm 2014-11-26 21:45:50.000000000 +0000 @@ -780,7 +780,7 @@ isWebIDEWidgetInstalled: function() { let widgetWrapper = CustomizableUI.getWidget("webide-button"); - return !!(widgetWrapper && widgetWrapper.instances.some(i => !!i.node)); + return !!(widgetWrapper && widgetWrapper.provider == CustomizableUI.PROVIDER_API); }, /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/options-panel.css thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/options-panel.css --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/options-panel.css 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/options-panel.css 2014-11-26 21:45:50.000000000 +0000 @@ -26,6 +26,11 @@ -moz-padding-start: 5px; } +#devtools-theme-box { + margin-left: 0px; + padding-left: 0px; +} + /* Snap to 50% width once there is not room for 3 columns anymore. This prevents having 2 columns showing in a row, but taking up only ~66% of the available space. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/selection.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/selection.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/selection.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/selection.js 2014-11-26 21:45:50.000000000 +0000 @@ -251,7 +251,7 @@ isHTMLNode: function() { let xhtml_ns = "http://www.w3.org/1999/xhtml"; - return this.isNode() && this.node.namespaceURI == xhtml_ns; + return this.isNode() && this.nodeFront.namespaceURI == xhtml_ns; }, // Node type @@ -300,6 +300,24 @@ return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.DOCUMENT_NODE; }, + /** + * @returns true if the selection is the HTML element. + */ + isBodyNode: function() { + return this.isHTMLNode() && + this.isConnected() && + this.nodeFront.nodeName === "BODY"; + }, + + /** + * @returns true if the selection is the HTML element. + */ + isHeadNode: function() { + return this.isHTMLNode() && + this.isConnected() && + this.nodeFront.nodeName === "HEAD"; + }, + isDocumentTypeNode: function() { return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE; }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/target.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/target.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/target.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/target.js 2014-11-26 21:45:50.000000000 +0000 @@ -280,6 +280,13 @@ if (!this.client) { throw new Error("TabTarget#getTrait() can only be called on remote tabs."); } + + // If the targeted actor exposes traits and has a defined value for this traits, + // override the root actor traits + if (this.form.traits && traitName in this.form.traits) { + return this.form.traits[traitName]; + } + return this.client.traits[traitName]; }, @@ -323,9 +330,13 @@ }, get name() { - return this._tab && this._tab.linkedBrowser.contentDocument ? - this._tab.linkedBrowser.contentDocument.title : - this._form.title; + if (this._tab && this._tab.linkedBrowser.contentDocument) { + return this._tab.linkedBrowser.contentDocument.title + } else if (this.isAddon) { + return this._form.name; + } else { + return this._form.title; + } }, get url() { @@ -338,7 +349,8 @@ }, get isAddon() { - return !!(this._form && this._form.addonActor); + return !!(this._form && this._form.actor && + this._form.actor.match(/conn\d+\.addon\d+/)); }, get isLocalTab() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/test/browser_devtools_api.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/test/browser_devtools_api.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/test/browser_devtools_api.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/test/browser_devtools_api.js 2014-11-26 21:45:50.000000000 +0000 @@ -4,10 +4,13 @@ /////////////////// // // Whitelisting this test. -// As part of bug 1077403, the leaking uncaught rejection should be fixed. +// As part of bug 1077403, the leaking uncaught rejections should be fixed. // thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null"); +// When running in a standalone directory, we get this error +thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.doc is undefined"); + // Tests devtools API const Cu = Components.utils; @@ -76,7 +79,10 @@ gDevTools.unregisterTool(toolId1); - runTests2(); + // Wait for unregisterTool to select the next tool before calling runTests2, + // otherwise we will receive the wrong select event when waiting for + // unregisterTool to select the next tool in continueTests below. + toolbox.once("select", runTests2); }); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/test/browser.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/test/browser.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/test/browser.ini 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/test/browser.ini 2014-11-26 21:45:50.000000000 +0000 @@ -22,6 +22,7 @@ [browser_toolbox_highlight.js] [browser_toolbox_hosts.js] [browser_toolbox_options.js] +[browser_toolbox_options_devedition.js] [browser_toolbox_options_disable_buttons.js] [browser_toolbox_options_disable_cache.js] skip-if = e10s # Bug 1030318 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/test/browser_toolbox_options_devedition.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/test/browser_toolbox_options_devedition.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/test/browser_toolbox_options_devedition.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/test/browser_toolbox_options_devedition.js 2014-11-26 21:45:50.000000000 +0000 @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that changing preferences in the options panel updates the prefs +// and toggles appropriate things in the toolbox. + +let doc = null, toolbox = null, panelWin = null; + +const PREF_ENABLED = "browser.devedition.theme.enabled"; +const PREF_SHOW = "browser.devedition.theme.showCustomizeButton"; + +const URL = "data:text/html;charset=utf8,test for toggling dev edition browser theme toggling"; + +let test = asyncTest(function*() { + // Set preference to false by default so this could + // run in Developer Edition which has it on by default. + Services.prefs.setBoolPref(PREF_ENABLED, false); + Services.prefs.setBoolPref(PREF_SHOW, true); + + let tab = yield addTab(URL); + let target = TargetFactory.forTab(tab); + toolbox = yield gDevTools.showToolbox(target); + let tool = yield toolbox.selectTool("options"); + panelWin = tool.panelWin; + + let checkbox = tool.panelDoc.getElementById("devtools-browser-theme"); + + ise(Services.prefs.getBoolPref(PREF_ENABLED), false, "Dev Theme pref off on start"); + + let themeStatus = yield clickAndWaitForThemeChange(checkbox, panelWin); + ise(themeStatus, true, "Theme has been toggled on."); + + themeStatus = yield clickAndWaitForThemeChange(checkbox, panelWin); + ise(themeStatus, false, "Theme has been toggled off."); + + yield cleanup(); +}); + +function clickAndWaitForThemeChange (el, win) { + let deferred = promise.defer(); + gDevTools.on("pref-changed", function handler (event, {pref}) { + if (pref === PREF_ENABLED) { + gDevTools.off("pref-changed", handler); + deferred.resolve(Services.prefs.getBoolPref(PREF_ENABLED)); + } + }); + + EventUtils.synthesizeMouseAtCenter(el, {}, win); + + return deferred.promise; +} + +function* cleanup() { + yield toolbox.destroy(); + gBrowser.removeCurrentTab(); + Services.prefs.clearUserPref(PREF_ENABLED); + Services.prefs.clearUserPref(PREF_SHOW); + toolbox = doc = panelWin = null; +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox.js 2014-11-26 21:45:50.000000000 +0000 @@ -53,11 +53,12 @@ // (By default, supported target is only local tab) const ToolboxButtons = [ { id: "command-button-pick", - isTargetSupported: target => !target.isAddon }, + isTargetSupported: target => + target.getTrait("highlightable") + }, { id: "command-button-frames", - isTargetSupported: target => ( - !target.isAddon && target.activeTab && target.activeTab.traits.frames - ) + isTargetSupported: target => + ( target.activeTab && target.activeTab.traits.frames ) }, { id: "command-button-splitconsole", isTargetSupported: target => !target.isAddon }, @@ -1249,12 +1250,15 @@ toolName = toolboxStrings("toolbox.defaultTitle"); } let title = toolboxStrings("toolbox.titleTemplate", - toolName, this.target.url || this.target.name); + toolName, + this.target.isAddon ? + this.target.name : + this.target.url || this.target.name); this._host.setTitle(title); }, _listFrames: function (event) { - if (!this._target.form || !this._target.form.actor) { + if (!this._target.activeTab || !this._target.activeTab.traits.frames) { // We are not targetting a regular TabActor // it can be either an addon or browser toolbox actor return promise.resolve(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox-options.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox-options.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox-options.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox-options.js 2014-11-26 21:45:50.000000000 +0000 @@ -9,6 +9,9 @@ const promise = require("promise"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "CustomizeMode", "resource:///modules/CustomizeMode.jsm"); +const kDeveditionChangedNotification = "devedition-theme-state-changed"; +const DEVEDITION_THEME_PREF = "browser.devedition.theme.enabled"; exports.OptionsPanel = OptionsPanel; @@ -71,6 +74,7 @@ function OptionsPanel(iframeWindow, toolbox) { this.panelDoc = iframeWindow.document; this.panelWin = iframeWindow; + this.toolbox = toolbox; this.isReady = false; @@ -80,6 +84,7 @@ this._addListeners(); + Services.obs.addObserver(this, kDeveditionChangedNotification, false); const EventEmitter = require("devtools/toolkit/event-emitter"); EventEmitter.decorate(this); } @@ -104,6 +109,7 @@ this.setupToolsList(); this.setupToolbarButtonsList(); this.setupThemeList(); + this.setupBrowserThemeButton(); this.populatePreferences(); this.updateDefaultTheme(); @@ -142,6 +148,8 @@ } else if (data.pref === "devtools.theme") { this.updateCurrentTheme(); + } else if (data.pref === "browser.devedition.theme.enabled") { + this.updateBrowserTheme(); } }, @@ -277,18 +285,58 @@ this.updateCurrentTheme(); }, + /** + * Similar to `populatePrefs`, except we want more + * special rules for the browser theme button. + */ + setupBrowserThemeButton: function() { + let checkbox = this.panelDoc.getElementById("devtools-browser-theme"); + + checkbox.addEventListener("command", function() { + setPrefAndEmit(DEVEDITION_THEME_PREF, this.checked); + }.bind(checkbox)); + + this.updateBrowserThemeButton(); + }, + + /** + * Called on theme changed via observer of "devedition-theme-state-changed". + */ + updateBrowserThemeButton: function() { + let checkbox = this.panelDoc.getElementById("devtools-browser-theme"); + + // Check if the dev edition style sheet is applied -- will not + // be applied when dev edition theme is disabled, or when there's + // a LWT applied. + if (this._isDevEditionThemeOn()) { + checkbox.setAttribute("checked", "true"); + } else { + checkbox.removeAttribute("checked"); + } + + // Should the button be shown + if (GetPref("browser.devedition.theme.showCustomizeButton")) { + checkbox.removeAttribute("hidden"); + } else { + checkbox.setAttribute("hidden", "true"); + } + }, + + /** + * Called when clicking the browser theme button to enable/disable + * the dev edition browser theme. + */ + updateBrowserTheme: function() { + let enabled = GetPref("browser.devedition.theme.enabled"); + CustomizeMode.prototype.toggleDevEditionTheme.call(this, enabled); + }, + populatePreferences: function() { let prefCheckboxes = this.panelDoc.querySelectorAll("checkbox[data-pref]"); for (let checkbox of prefCheckboxes) { checkbox.checked = GetPref(checkbox.getAttribute("data-pref")); checkbox.addEventListener("command", function() { - let data = { - pref: this.getAttribute("data-pref"), - newValue: this.checked - }; - data.oldValue = GetPref(data.pref); - SetPref(data.pref, data.newValue); - gDevTools.emit("pref-changed", data); + setPrefAndEmit(this.getAttribute("data-pref"), this.checked); }.bind(checkbox)); } let prefRadiogroups = this.panelDoc.querySelectorAll("radiogroup[data-pref]"); @@ -302,17 +350,7 @@ } } radiogroup.addEventListener("select", function() { - let data = { - pref: this.getAttribute("data-pref"), - newValue: this.selectedItem.getAttribute("value") - }; - - data.oldValue = GetPref(data.pref); - SetPref(data.pref, data.newValue); - - if (data.newValue != data.oldValue) { - gDevTools.emit("pref-changed", data); - } + setPrefAndEmit(this.getAttribute("data-pref"), this.selectedItem.getAttribute("value")); }.bind(radiogroup)); } let prefMenulists = this.panelDoc.querySelectorAll("menulist[data-pref]"); @@ -327,13 +365,7 @@ } } menulist.addEventListener("command", function() { - let data = { - pref: this.getAttribute("data-pref"), - newValue: this.value - }; - data.oldValue = GetPref(data.pref); - SetPref(data.pref, data.newValue); - gDevTools.emit("pref-changed", data); + setPrefAndEmit(this.getAttribute("data-pref"), this.value); }.bind(menulist)); } @@ -388,6 +420,25 @@ this.target.activeTab.reconfigure(options); }, + /** + * Returns a boolean indicating whether or not the dev edition + * browser theme is applied. + */ + _isDevEditionThemeOn: function() { + let win = Services.wm.getMostRecentWindow("navigator:browser"); + return !!(win && win.DevEdition.styleSheet); + }, + + /** + * Called on observer notification for "devedition-theme-state-changed" + * to possibly change the state of the dev edition button + */ + observe: function(aSubject, aTopic, aData) { + if (aTopic === kDeveditionChangedNotification) { + this.updateBrowserThemeButton(); + } + }, + destroy: function() { if (this.destroyPromise) { return this.destroyPromise; @@ -414,6 +465,22 @@ deferred.resolve(); }, true); + Services.obs.removeObserver(this, kDeveditionChangedNotification); + return deferred.promise; } }; + +/* Set a pref and emit the pref-changed event if needed. */ +function setPrefAndEmit(prefName, newValue) { + let data = { + pref: prefName, + newValue: newValue + }; + data.oldValue = GetPref(data.pref); + SetPref(data.pref, data.newValue); + + if (data.newValue != data.oldValue) { + gDevTools.emit("pref-changed", data); + } +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox-options.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox-options.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox-options.xul 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox-options.xul 2014-11-26 21:45:50.000000000 +0000 @@ -28,12 +28,17 @@ - - - + + + + + + &options.defaultColorUnit.label; - - - - - - - - + + + + + + + + + + @@ -103,29 +110,33 @@ - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox-process-window.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox-process-window.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/framework/toolbox-process-window.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/framework/toolbox-process-window.js 2014-11-26 21:45:50.000000000 +0000 @@ -37,11 +37,7 @@ if (addonID) { gClient.listAddons(({addons}) => { let addonActor = addons.filter(addon => addon.id === addonID).pop(); - openToolbox({ - addonActor: addonActor.actor, - consoleActor: addonActor.consoleActor, - title: addonActor.name - }); + openToolbox(addonActor); }); } else { gClient.listTabs(openToolbox); @@ -53,6 +49,7 @@ function setPrefDefaults() { Services.prefs.setBoolPref("devtools.inspector.showUserAgentStyles", true); Services.prefs.setBoolPref("devtools.profiler.ui.show-platform-data", true); + Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", false); } window.addEventListener("load", function() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/inspector/inspector-panel.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/inspector/inspector-panel.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/inspector/inspector-panel.js 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/inspector/inspector-panel.js 2014-11-26 21:45:50.000000000 +0000 @@ -57,7 +57,6 @@ this.panelDoc = iframeWindow.document; this.panelWin = iframeWindow; this.panelWin.inspector = this; - this._inspector = null; this._onBeforeNavigate = this._onBeforeNavigate.bind(this); this._target.on("will-navigate", this._onBeforeNavigate); @@ -109,6 +108,10 @@ return this._target.client.traits.getUniqueSelector; }, + get canPasteInnerOrAdjacentHTML() { + return this._target.client.traits.pasteHTML; + }, + _deferredOpen: function(defaultSelection) { let deferred = promise.defer(); @@ -573,7 +576,7 @@ * Returns the clipboard content if it is appropriate for pasting * into the current node's outer HTML, otherwise returns null. */ - _getClipboardContentForOuterHTML: function Inspector_getClipboardContentForOuterHTML() { + _getClipboardContentForPaste: function Inspector_getClipboardContentForPaste() { let flavors = clipboard.currentFlavors; if (flavors.indexOf("text") != -1 || (flavors.indexOf("html") != -1 && flavors.indexOf("image") == -1)) { @@ -642,15 +645,34 @@ editHTML.setAttribute("disabled", "true"); } - // Enable the "paste outer HTML" item if the selection is an element and - // the root actor has the appropriate trait (isOuterHTMLEditable) and if - // the clipbard content is appropriate. let pasteOuterHTML = this.panelDoc.getElementById("node-menu-pasteouterhtml"); - if (isEditableElement && this.isOuterHTMLEditable && - this._getClipboardContentForOuterHTML()) { - pasteOuterHTML.removeAttribute("disabled"); + let pasteInnerHTML = this.panelDoc.getElementById("node-menu-pasteinnerhtml"); + let pasteBefore = this.panelDoc.getElementById("node-menu-pastebefore"); + let pasteAfter = this.panelDoc.getElementById("node-menu-pasteafter"); + let pasteFirstChild = this.panelDoc.getElementById("node-menu-pastefirstchild"); + let pasteLastChild = this.panelDoc.getElementById("node-menu-pastelastchild"); + + // Is the clipboard content appropriate? Is the element editable? + if (isEditableElement && this._getClipboardContentForPaste()) { + pasteInnerHTML.disabled = !this.canPasteInnerOrAdjacentHTML; + // Enable the "paste outer HTML" item if the selection is an element and + // the root actor has the appropriate trait (isOuterHTMLEditable). + pasteOuterHTML.disabled = !this.isOuterHTMLEditable; + // Don't paste before / after a root or a BODY or a HEAD element. + pasteBefore.disabled = pasteAfter.disabled = + !this.canPasteInnerOrAdjacentHTML || this.selection.isRoot() || + this.selection.isBodyNode() || this.selection.isHeadNode(); + // Don't paste as a first / last child of a HTML document element. + pasteFirstChild.disabled = pasteLastChild.disabled = + !this.canPasteInnerOrAdjacentHTML || (this.selection.isHTMLNode() && + this.selection.isRoot()); } else { - pasteOuterHTML.setAttribute("disabled", "true"); + pasteOuterHTML.disabled = true; + pasteInnerHTML.disabled = true; + pasteBefore.disabled = true; + pasteAfter.disabled = true; + pasteFirstChild.disabled = true; + pasteLastChild.disabled = true; } // Enable the "copy image data-uri" item if the selection is previewable @@ -690,7 +712,7 @@ this._markupBox.setAttribute("collapsed", true); this._markupBox.appendChild(this._markupFrame); this._markupFrame.setAttribute("src", "chrome://browser/content/devtools/markup-view.xhtml"); - this._markupFrame.setAttribute("aria-label", this.strings.GetStringFromName("inspector.panelLabel.markupView")) + this._markupFrame.setAttribute("aria-label", this.strings.GetStringFromName("inspector.panelLabel.markupView")); }, _onMarkupFrameLoad: function InspectorPanel__onMarkupFrameLoad() { @@ -773,8 +795,7 @@ /** * Edit the outerHTML of the selected Node. */ - editHTML: function InspectorPanel_editHTML() - { + editHTML: function InspectorPanel_editHTML() { if (!this.selection.isNode()) { return; } @@ -786,22 +807,49 @@ /** * Paste the contents of the clipboard into the selected Node's outer HTML. */ - pasteOuterHTML: function InspectorPanel_pasteOuterHTML() - { - let content = this._getClipboardContentForOuterHTML(); - if (content) { - let node = this.selection.nodeFront; - this.markup.getNodeOuterHTML(node).then((oldContent) => { - this.markup.updateNodeOuterHTML(node, content, oldContent); - }); - } + pasteOuterHTML: function InspectorPanel_pasteOuterHTML() { + let content = this._getClipboardContentForPaste(); + if (!content) + return promise.reject("No clipboard content for paste"); + + let node = this.selection.nodeFront; + return this.markup.getNodeOuterHTML(node).then(oldContent => { + this.markup.updateNodeOuterHTML(node, content, oldContent); + }); + }, + + /** + * Paste the contents of the clipboard into the selected Node's inner HTML. + */ + pasteInnerHTML: function InspectorPanel_pasteInnerHTML() { + let content = this._getClipboardContentForPaste(); + if (!content) + return promise.reject("No clipboard content for paste"); + + let node = this.selection.nodeFront; + return this.markup.getNodeInnerHTML(node).then(oldContent => { + this.markup.updateNodeInnerHTML(node, content, oldContent); + }); + }, + + /** + * Paste the contents of the clipboard as adjacent HTML to the selected Node. + * @param position The position as specified for Element.insertAdjacentHTML + * (i.e. "beforeBegin", "afterBegin", "beforeEnd", "afterEnd"). + */ + pasteAdjacentHTML: function InspectorPanel_pasteAdjacent(position) { + let content = this._getClipboardContentForPaste(); + if (!content) + return promise.reject("No clipboard content for paste"); + + let node = this.selection.nodeFront; + return this.markup.insertAdjacentHTMLToNode(node, position, content); }, /** * Copy the innerHTML of the selected Node to the clipboard. */ - copyInnerHTML: function InspectorPanel_copyInnerHTML() - { + copyInnerHTML: function InspectorPanel_copyInnerHTML() { if (!this.selection.isNode()) { return; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/inspector/inspector.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/inspector/inspector.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/browser/devtools/inspector/inspector.xul 2014-11-14 09:37:14.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/browser/devtools/inspector/inspector.xul 2014-11-26 21:45:50.000000000 +0000 @@ -59,10 +59,36 @@ label="&inspectorShowDOMProperties.label;" oncommand="inspector.showDOMProperties()"/> + + + + + + + + +
@@ -317,7 +317,7 @@
&nssFailure2.longDesc2;
&nssBadCert.longDesc2;
&malwareBlocked.longDesc;
-
&cspFrameAncestorBlocked.longDesc;
+
&cspBlocked.longDesc;
&remoteXUL.longDesc;
&corruptedContentError.longDesc;
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/public/nsISHContainer.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/public/nsISHContainer.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/public/nsISHContainer.idl 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/public/nsISHContainer.idl 2014-11-26 21:45:54.000000000 +0000 @@ -14,7 +14,7 @@ * */ -[scriptable, uuid(65281BA2-988A-11d3-BDC7-0050040A9B44)] +[scriptable, uuid(67dd0357-8372-4122-bff6-217435e8b7e4)] interface nsISHContainer : nsISupports { /** @@ -38,5 +38,12 @@ */ nsISHEntry GetChildAt(in long index); + /** + * Replaces a child which is for the same docshell as aNewChild + * with aNewChild. + * @throw if nothing was replaced. + */ + void ReplaceChild(in nsISHEntry aNewChild); + }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/public/nsISHEntry.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/public/nsISHEntry.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/public/nsISHEntry.idl 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/public/nsISHEntry.idl 2014-11-26 21:45:54.000000000 +0000 @@ -30,7 +30,7 @@ [ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData); [ptr] native nsSHEntryShared(nsSHEntryShared); -[scriptable, uuid(9eed7e92-1121-46f2-95e5-2f5c0dca46f0)] +[scriptable, uuid(d5fbeb10-f373-4677-b69a-2694aa706cac)] interface nsISHEntry : nsISupports { /** @@ -64,6 +64,11 @@ /** Referrer URI */ attribute nsIURI referrerURI; + /** Referrer policy, holding one of the values (REFERRER_POLICY_*) + * defined in nsIHttpChannel. + */ + attribute unsigned long referrerPolicy; + /** Content viewer, for fast restoration of presentation */ attribute nsIContentViewer contentViewer; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/src/nsSHEntry.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/src/nsSHEntry.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/src/nsSHEntry.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/src/nsSHEntry.cpp 2014-11-26 21:45:54.000000000 +0000 @@ -15,6 +15,7 @@ #include "nsIStructuredCloneContainer.h" #include "nsIInputStream.h" #include "nsIURI.h" +#include "mozilla/net/ReferrerPolicy.h" #include namespace dom = mozilla::dom; @@ -27,7 +28,8 @@ nsSHEntry::nsSHEntry() - : mLoadType(0) + : mReferrerPolicy(mozilla::net::RP_Default) + , mLoadType(0) , mID(gEntryID++) , mScrollPositionX(0) , mScrollPositionY(0) @@ -42,6 +44,7 @@ : mShared(other.mShared) , mURI(other.mURI) , mReferrerURI(other.mReferrerURI) + , mReferrerPolicy(other.mReferrerPolicy) , mTitle(other.mTitle) , mPostData(other.mPostData) , mLoadType(0) // XXX why not copy? @@ -134,6 +137,18 @@ return NS_OK; } +NS_IMETHODIMP nsSHEntry::GetReferrerPolicy(uint32_t *aReferrerPolicy) +{ + *aReferrerPolicy = mReferrerPolicy; + return NS_OK; +} + +NS_IMETHODIMP nsSHEntry::SetReferrerPolicy(uint32_t aReferrerPolicy) +{ + mReferrerPolicy = aReferrerPolicy; + return NS_OK; +} + NS_IMETHODIMP nsSHEntry::SetContentViewer(nsIContentViewer *aViewer) { @@ -691,6 +706,27 @@ } NS_IMETHODIMP +nsSHEntry::ReplaceChild(nsISHEntry* aNewEntry) +{ + NS_ENSURE_STATE(aNewEntry); + + uint64_t docshellID; + aNewEntry->GetDocshellID(&docshellID); + + uint64_t otherID; + for (int32_t i = 0; i < mChildren.Count(); ++i) { + if (mChildren[i] && NS_SUCCEEDED(mChildren[i]->GetDocshellID(&otherID)) && + docshellID == otherID) { + mChildren[i]->SetParent(nullptr); + if (mChildren.ReplaceObjectAt(aNewEntry, i)) { + return aNewEntry->SetParent(this); + } + } + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsSHEntry::AddChildShell(nsIDocShellTreeItem *aShell) { NS_ASSERTION(aShell, "Null child shell added to history entry"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/src/nsSHEntry.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/src/nsSHEntry.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/shistory/src/nsSHEntry.h 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/shistory/src/nsSHEntry.h 2014-11-26 21:45:54.000000000 +0000 @@ -50,6 +50,7 @@ // See nsSHEntry.idl for comments on these members. nsCOMPtr mURI; nsCOMPtr mReferrerURI; + uint32_t mReferrerPolicy; nsString mTitle; nsCOMPtr mPostData; uint32_t mLoadType; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_bug441169.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_bug441169.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_bug441169.js 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_bug441169.js 2014-11-26 21:45:54.000000000 +0000 @@ -17,7 +17,11 @@ newBrowser.contentWindow.location = chromeURL; } -function checkPage() { +function checkPage(event) { + if (event.target != gBrowser.selectedBrowser.contentDocument) { + return; + } + window.removeEventListener("DOMContentLoaded", checkPage, false); is(newBrowser.contentDocument.getElementById("test_span"), null, "Error message should not be parsed as HTML, and hence shouldn't include the 'test_span' element."); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_timelineMarkers-02.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_timelineMarkers-02.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_timelineMarkers-02.js 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_timelineMarkers-02.js 2014-11-26 21:45:54.000000000 +0000 @@ -54,7 +54,8 @@ content.console.timeEnd("FOOBAR"); let markers = docShell.popProfileTimelineMarkers(); is(markers.length, 1, "Got one marker"); - is(markers[0].name, "ConsoleTime:FOOBAR", "Got ConsoleTime:FOOBAR marker"); + is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker"); + is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail"); content.console.time("FOO"); content.setTimeout(() => { content.console.time("BAR"); @@ -66,8 +67,10 @@ }, check: function(markers) { is(markers.length, 2, "Got 2 markers"); - is(markers[0].name, "ConsoleTime:FOO", "Got ConsoleTime:FOO marker"); - is(markers[1].name, "ConsoleTime:BAR", "Got ConsoleTime:BARmarker"); + is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker"); + is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail"); + is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker"); + is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail"); } }]; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_timelineMarkers-03.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_timelineMarkers-03.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_timelineMarkers-03.js 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_timelineMarkers-03.js 2014-11-26 21:45:54.000000000 +0000 @@ -16,6 +16,8 @@ }, check: function(markers) { is(markers.length, 1, "Got 1 marker"); + is(markers[0].type, "dog", "Got dog event name"); + is(markers[0].eventPhase, 2, "Got phase 2"); } }, { desc: "Event dispatch with a second handler", @@ -29,6 +31,18 @@ is(markers.length, 2, "Got 2 markers"); } }, { + desc: "Event targeted at child", + setup: function() { + let child = content.document.body.firstElementChild; + child.addEventListener("dog", function(e) { }); + child.dispatchEvent(new Event("dog")); + }, + check: function(markers) { + is(markers.length, 2, "Got 2 markers"); + is(markers[0].eventPhase, 1, "Got phase 1 marker"); + is(markers[1].eventPhase, 2, "Got phase 2 marker"); + } +}, { desc: "Event dispatch on a new document", setup: function() { let doc = content.document.implementation.createHTMLDocument("doc"); @@ -59,7 +73,7 @@ let test = Task.async(function*() { waitForExplicitFinish(); - yield openUrl("data:text/html;charset=utf-8,Test page"); + yield openUrl("data:text/html;charset=utf-8,

Test page

"); let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_timelineMarkers-04.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_timelineMarkers-04.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/browser_timelineMarkers-04.js 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/browser_timelineMarkers-04.js 2014-11-26 21:45:54.000000000 +0000 @@ -43,13 +43,13 @@ docShell.popProfileTimelineMarkers(); info("Running the test setup function"); - let onMarkers = waitForMarkers(docShell); + let onMarkers = waitForDOMMarkers(docShell, 5); setup(); info("Waiting for new markers on the docShell"); let markers = yield onMarkers; info("Running the test check function"); - check(markers.filter(m => m.name == "DOMEvent")); + check(markers); } info("Stop recording"); @@ -73,21 +73,20 @@ }); } -function waitForMarkers(docshell) { +function waitForDOMMarkers(docshell, numExpected) { return new Promise(function(resolve, reject) { let waitIterationCount = 0; let maxWaitIterationCount = 10; // Wait for 2sec maximum + let markers = []; let interval = setInterval(() => { - let markers = docshell.popProfileTimelineMarkers(); - if (markers.length > 0) { + let newMarkers = docshell.popProfileTimelineMarkers(); + markers = [...markers, ...newMarkers.filter(m => m.name == "DOMEvent")]; + if (markers.length >= numExpected + || waitIterationCount > maxWaitIterationCount) { clearInterval(interval); resolve(markers); } - if (waitIterationCount > maxWaitIterationCount) { - clearInterval(interval); - resolve([]); - } waitIterationCount++; }, 200); }); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/timelineMarkers-04.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/timelineMarkers-04.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/browser/timelineMarkers-04.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/browser/timelineMarkers-04.html 2014-11-26 21:45:54.000000000 +0000 @@ -14,7 +14,7 @@ xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { - // Nothing. + dump("ReadyState = " + xhr.readyState + "\n"); }; xhr.open("get", theURL, true); xhr.send(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/bug530396-subframe.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/bug530396-subframe.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/bug530396-subframe.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/bug530396-subframe.html 2014-11-26 21:45:54.000000000 +0000 @@ -1,7 +1,7 @@ - bug530396-noref.sjs - bug530396-noref.sjs with new window + bug530396-noref.sjs + bug530396-noref.sjs with new window diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/navigation/file_nested_frames.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/navigation/file_nested_frames.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/navigation/file_nested_frames.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/navigation/file_nested_frames.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,28 @@ + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/navigation/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/navigation/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/navigation/mochitest.ini 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/navigation/mochitest.ini 2014-11-26 21:45:54.000000000 +0000 @@ -9,6 +9,7 @@ file_bug534178.html file_document_write_1.html file_fragment_handling_during_load.html + file_nested_frames.html file_static_and_dynamic_1.html frame0.html frame1.html diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/navigation/test_sessionhistory.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/navigation/test_sessionhistory.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/docshell/test/navigation/test_sessionhistory.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/docshell/test/navigation/test_sessionhistory.html 2014-11-26 21:45:54.000000000 +0000 @@ -27,7 +27,8 @@ "file_document_write_1.html", // Session history + document.write //"file_static_and_dynamic_1.html",// Static and dynamic frames and forward-back "file_bug534178.html", // Session history transaction clean-up. - "file_fragment_handling_during_load.html" + "file_fragment_handling_during_load.html", + "file_nested_frames.html" ]; var testCount = 0; // Used by the test files. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/AnimationPlayer.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/AnimationPlayer.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/AnimationPlayer.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/AnimationPlayer.cpp 2014-11-26 21:45:54.000000000 +0000 @@ -6,6 +6,10 @@ #include "AnimationPlayer.h" #include "AnimationUtils.h" #include "mozilla/dom/AnimationPlayerBinding.h" +#include "AnimationCommon.h" // For AnimationPlayerCollection, + // CommonAnimationManager +#include "nsIDocument.h" // For nsIDocument +#include "nsIPresShell.h" // For nsIPresShell #include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336) namespace mozilla { @@ -63,50 +67,17 @@ } void -AnimationPlayer::Play(UpdateFlags aFlags) +AnimationPlayer::Play() { - // FIXME: When we implement finishing behavior (bug 1074630) we should - // not return early if mIsPaused is false since we may still need to seek. - // (However, we will need to pass a flag so that when we start playing due to - // a change in animation-play-state we *don't* trigger finishing behavior.) - if (!mIsPaused) { - return; - } - mIsPaused = false; - - Nullable timelineTime = mTimeline->GetCurrentTime(); - if (timelineTime.IsNull()) { - // FIXME: We should just sit in the pending state in this case. - // We will introduce the pending state in Bug 927349. - return; - } - - // Update start time to an appropriate offset from the current timeline time - MOZ_ASSERT(!mHoldTime.IsNull(), "Hold time should not be null when paused"); - mStartTime.SetValue(timelineTime.Value() - mHoldTime.Value()); - mHoldTime.SetNull(); - - if (aFlags == eUpdateStyle) { - MaybePostRestyle(); - } + DoPlay(); + PostUpdate(); } void -AnimationPlayer::Pause(UpdateFlags aFlags) +AnimationPlayer::Pause() { - if (mIsPaused) { - return; - } - mIsPaused = true; - mIsRunningOnCompositor = false; - - // Bug 927349 - check for null result here and go to pending state - mHoldTime = GetCurrentTime(); - mStartTime.SetNull(); - - if (aFlags == eUpdateStyle) { - MaybePostRestyle(); - } + DoPause(); + PostUpdate(); } Nullable @@ -115,40 +86,6 @@ return AnimationUtils::TimeDurationToDouble(GetCurrentTime()); } -AnimationPlayState -AnimationPlayer::PlayStateFromJS() const -{ - // FIXME: Once we introduce CSSTransitionPlayer, this should move to an - // override of PlayStateFromJS in CSSAnimationPlayer and CSSTransitionPlayer - // and we should skip it in the general case. - FlushStyle(); - - return PlayState(); -} - -void -AnimationPlayer::PlayFromJS() -{ - // Flush style to ensure that any properties controlling animation state - // (e.g. animation-play-state) are fully updated before we proceed. - // - // Note that this might trigger PlayFromStyle()/PauseFromStyle() on this - // object. - // - // FIXME: Once we introduce CSSTransitionPlayer, this should move to an - // override of PlayFromJS in CSSAnimationPlayer and CSSTransitionPlayer and - // we should skip it in the general case. - FlushStyle(); - - Play(eUpdateStyle); -} - -void -AnimationPlayer::PauseFromJS() -{ - Pause(eUpdateStyle); -} - void AnimationPlayer::SetSource(Animation* aSource) { @@ -225,55 +162,120 @@ } void -AnimationPlayer::FlushStyle() const +AnimationPlayer::DoPlay() { - if (!mSource) { + // FIXME: When we implement finishing behavior (bug 1074630) we should + // not return early if mIsPaused is false since we may still need to seek. + // (However, we will need to pass a flag so that when we start playing due to + // a change in animation-play-state we *don't* trigger finishing behavior.) + if (!mIsPaused) { return; } + mIsPaused = false; - Element* targetElement; - nsCSSPseudoElements::Type pseudoType; - mSource->GetTarget(targetElement, pseudoType); - if (!targetElement) { + Nullable timelineTime = mTimeline->GetCurrentTime(); + if (timelineTime.IsNull()) { + // FIXME: We should just sit in the pending state in this case. + // We will introduce the pending state in Bug 927349. return; } - nsIDocument* doc = targetElement->GetComposedDoc(); + // Update start time to an appropriate offset from the current timeline time + MOZ_ASSERT(!mHoldTime.IsNull(), "Hold time should not be null when paused"); + mStartTime.SetValue(timelineTime.Value() - mHoldTime.Value()); + mHoldTime.SetNull(); +} + +void +AnimationPlayer::DoPause() +{ + if (mIsPaused) { + return; + } + mIsPaused = true; + mIsRunningOnCompositor = false; + + // Bug 927349 - check for null result here and go to pending state + mHoldTime = GetCurrentTime(); + mStartTime.SetNull(); +} + +void +AnimationPlayer::FlushStyle() const +{ + nsIDocument* doc = GetRenderedDocument(); if (doc) { doc->FlushPendingNotifications(Flush_Style); } } void -AnimationPlayer::MaybePostRestyle() const +AnimationPlayer::PostUpdate() +{ + AnimationPlayerCollection* collection = GetCollection(); + if (collection) { + collection->NotifyPlayerUpdated(); + } +} + +StickyTimeDuration +AnimationPlayer::SourceContentEnd() const { if (!mSource) { - return; + return StickyTimeDuration(0); + } + + return mSource->Timing().mDelay + + mSource->GetComputedTiming().mActiveDuration; +} + +nsIDocument* +AnimationPlayer::GetRenderedDocument() const +{ + if (!mSource) { + return nullptr; } Element* targetElement; nsCSSPseudoElements::Type pseudoType; mSource->GetTarget(targetElement, pseudoType); if (!targetElement) { - return; + return nullptr; } - // FIXME: This is a bit heavy-handed but in bug 1073336 we hope to - // introduce a better means for players to update style. - nsLayoutUtils::PostRestyleEvent(targetElement, - eRestyle_Self, - nsChangeHint_AllReflowHints); + return targetElement->GetComposedDoc(); } -StickyTimeDuration -AnimationPlayer::SourceContentEnd() const +nsPresContext* +AnimationPlayer::GetPresContext() const { - if (!mSource) { - return StickyTimeDuration(0); + nsIDocument* doc = GetRenderedDocument(); + if (!doc) { + return nullptr; + } + nsIPresShell* shell = doc->GetShell(); + if (!shell) { + return nullptr; + } + return shell->GetPresContext(); +} + +AnimationPlayerCollection* +AnimationPlayer::GetCollection() const +{ + css::CommonAnimationManager* manager = GetAnimationManager(); + if (!manager) { + return nullptr; } + MOZ_ASSERT(mSource, "A player with an animation manager must have a source"); - return mSource->Timing().mDelay - + mSource->GetComputedTiming().mActiveDuration; + Element* targetElement; + nsCSSPseudoElements::Type targetPseudoType; + mSource->GetTarget(targetElement, targetPseudoType); + MOZ_ASSERT(targetElement, + "A player with an animation manager must have a target"); + + return manager->GetAnimationPlayers(targetElement, targetPseudoType, false); } } // namespace dom diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/AnimationPlayer.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/AnimationPlayer.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/AnimationPlayer.h 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/AnimationPlayer.h 2014-11-26 21:45:54.000000000 +0000 @@ -22,13 +22,18 @@ struct JSContext; class nsCSSPropertySet; +class nsIDocument; +class nsPresContext; namespace mozilla { +struct AnimationPlayerCollection; namespace css { class AnimValuesStyleRule; +class CommonAnimationManager; } // namespace css class CSSAnimationPlayer; +class CSSTransitionPlayer; namespace dom { @@ -53,13 +58,7 @@ virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; virtual CSSAnimationPlayer* AsCSSAnimationPlayer() { return nullptr; } - - // Temporary flags to control restyle behavior until bug 1073336 - // provides a better solution. - enum UpdateFlags { - eNoUpdate, - eUpdateStyle - }; + virtual CSSTransitionPlayer* AsCSSTransitionPlayer() { return nullptr; } // AnimationPlayer methods Animation* GetSource() const { return mSource; } @@ -67,18 +66,21 @@ Nullable GetStartTime() const; Nullable GetCurrentTime() const; AnimationPlayState PlayState() const; - virtual void Play(UpdateFlags aUpdateFlags); - virtual void Pause(UpdateFlags aUpdateFlags); + virtual void Play(); + virtual void Pause(); bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; } // Wrapper functions for AnimationPlayer DOM methods when called // from script. We often use the same methods internally and from - // script but when called from script we perform extra steps such - // as flushing style or converting the return type. + // script but when called from script we (or one of our subclasses) perform + // extra steps such as flushing style or converting the return type. Nullable GetCurrentTimeAsDouble() const; - AnimationPlayState PlayStateFromJS() const; - void PlayFromJS(); - void PauseFromJS(); + virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); } + virtual void PlayFromJS() { Play(); } + // PauseFromJS is currently only here for symmetry with PlayFromJS but + // in future we will likely have to flush style in + // CSSAnimationPlayer::PauseFromJS so we leave it for now. + void PauseFromJS() { Pause(); } void SetSource(Animation* aSource); void Tick(); @@ -120,10 +122,18 @@ Nullable mStartTime; // Timeline timescale protected: + void DoPlay(); + void DoPause(); + void FlushStyle() const; - void MaybePostRestyle() const; + void PostUpdate(); StickyTimeDuration SourceContentEnd() const; + nsIDocument* GetRenderedDocument() const; + nsPresContext* GetPresContext() const; + virtual css::CommonAnimationManager* GetAnimationManager() const = 0; + AnimationPlayerCollection* GetCollection() const; + nsRefPtr mTimeline; nsRefPtr mSource; Nullable mHoldTime; // Player timescale diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-effect-name.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-effect-name.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-effect-name.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-effect-name.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,45 @@ + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-pausing.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-pausing.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-pausing.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-pausing.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,209 @@ + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-player-playstate.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-player-playstate.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-player-playstate.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-player-playstate.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,57 @@ + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animations-dynamic-changes.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animations-dynamic-changes.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animations-dynamic-changes.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animations-dynamic-changes.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,150 @@ + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-target.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-target.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_animation-target.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_animation-target.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,27 @@ + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_element-get-animation-players.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_element-get-animation-players.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-animations/test_element-get-animation-players.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-animations/test_element-get-animation-players.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,259 @@ + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-effect-name.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-effect-name.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-effect-name.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-effect-name.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-pausing.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-pausing.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-pausing.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-pausing.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,253 +0,0 @@ - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-player-playstate.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-player-playstate.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-player-playstate.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-player-playstate.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animations-dynamic-changes.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animations-dynamic-changes.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animations-dynamic-changes.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animations-dynamic-changes.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-target.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-target.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_animation-target.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_animation-target.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_element-get-animation-players.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_element-get-animation-players.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-integration/test_element-get-animation-players.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-integration/test_element-get-animation-players.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,344 +0,0 @@ - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_animation-effect-name.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_animation-effect-name.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_animation-effect-name.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_animation-effect-name.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,24 @@ + + + + +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_animation-pausing.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_animation-pausing.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_animation-pausing.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_animation-pausing.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,66 @@ + + + + +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_animation-target.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_animation-target.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_animation-target.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_animation-target.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,24 @@ + + + + +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_element-get-animation-players.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_element-get-animation-players.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/css-transitions/test_element-get-animation-players.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/css-transitions/test_element-get-animation-players.html 2014-11-26 21:45:54.000000000 +0000 @@ -0,0 +1,100 @@ + + + + +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/animation/test/mochitest.ini 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/animation/test/mochitest.ini 2014-11-26 21:45:54.000000000 +0000 @@ -1,9 +1,14 @@ [animation-timeline/test_animation-timeline.html] skip-if = buildapp == 'mulet' -[css-integration/test_element-get-animation-players.html] +[css-animations/test_animations-dynamic-changes.html] +[css-animations/test_animation-effect-name.html] +[css-animations/test_animation-pausing.html] +[css-animations/test_animation-player-playstate.html] +[css-animations/test_animation-target.html] +[css-animations/test_element-get-animation-players.html] +skip-if = buildapp == 'mulet' +[css-transitions/test_animation-effect-name.html] +[css-transitions/test_animation-pausing.html] +[css-transitions/test_animation-target.html] +[css-transitions/test_element-get-animation-players.html] skip-if = buildapp == 'mulet' -[css-integration/test_animations-dynamic-changes.html] -[css-integration/test_animation-effect-name.html] -[css-integration/test_animation-pausing.html] -[css-integration/test_animation-player-playstate.html] -[css-integration/test_animation-target.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/tests/file_packaged_app.sjs thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/tests/file_packaged_app.sjs --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/tests/file_packaged_app.sjs 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/tests/file_packaged_app.sjs 2014-11-26 21:45:54.000000000 +0000 @@ -30,6 +30,10 @@ var alreadyDeferred = Number(getState("alreadyDeferred")); var role = query.role || ""; + var failPackageDownloadOnce = "failPackageDownloadOnce" in query; + var failOnce = "failOnce" in query; + var alreadyFailed = Number(getState("alreadyFailed")); + if (allowCancel && getPackage && !alreadyDeferred) { // Only do this for the actual package delivery. response.processAsync(); @@ -37,6 +41,15 @@ setState("alreadyDeferred", "1"); } + if (failOnce && !alreadyFailed) { + setState("alreadyFailed", "1"); + // We need to simulate a network error... let's just try closing the connection + // without any output + response.seizePower(); + response.finish(); + return; + } + response.setHeader("Access-Control-Allow-Origin", "*", false); // If this is a version update, update state, prepare the manifest, @@ -49,8 +62,9 @@ setState("packageName", packageName); var packagePath = "/" + gBasePath + "file_packaged_app.sjs?" + - (allowCancel?"allowCancel&": "") + "getPackage=" + - packageName; + (allowCancel ? "allowCancel&" : "") + + (failPackageDownloadOnce ? "failOnce&" : "") + + "getPackage=" + packageName; setState("packagePath", packagePath); if (version == packageVersion) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/tests/test_packaged_app_common.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/tests/test_packaged_app_common.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/tests/test_packaged_app_common.js 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/tests/test_packaged_app_common.js 2014-11-26 21:45:55.000000000 +0000 @@ -57,17 +57,22 @@ finish(); } - function setAppVersion(aVersion, aCb, aDontUpdatePackage, aAllowCancel, aRole) { + function setAppVersion(aVersion, aCb, aDontUpdatePackage, aAllowCancel, aRole, aFailOnce) { var xhr = new XMLHttpRequest(); var dontUpdate = ""; var allowCancel = ""; + var failOnce = ""; if (aDontUpdatePackage) { dontUpdate = "&dontUpdatePackage=1"; } if (aAllowCancel) { allowCancel= "&allowCancel=1"; } - var url = gSJS + "?setVersion=" + aVersion + dontUpdate + allowCancel; + if (aFailOnce) { + failOnce = "&failPackageDownloadOnce=1"; + } + var url = gSJS + "?setVersion=" + aVersion + dontUpdate + allowCancel + + failOnce; if (aRole) { url += "&role=" + aRole; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/tests/test_packaged_app_update.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/tests/test_packaged_app_update.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/tests/test_packaged_app_update.html 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/tests/test_packaged_app_update.html 2014-11-26 21:45:55.000000000 +0000 @@ -72,12 +72,13 @@ expected, true, false, aCb); } -function updateApp(aExpectedReady, aPreviousVersion, aNextVersion) { +function updateApp(aExpectedReady, aPreviousVersion, aNextVersion, aFailOnError) { var lApp = PackagedTestHelper.gApp; var ondownloadappliedhandler = checkLastAppState.bind(PackagedTestHelper, miniManifestURL, false, false, - aNextVersion, PackagedTestHelper.next); + aNextVersion, + setTimeout.bind(undefined, PackagedTestHelper.next, 500)); var ondownloadsuccesshandler = checkLastAppState.bind(undefined, miniManifestURL, @@ -86,8 +87,15 @@ navigator.mozApps.mgmt.applyDownload(lApp); }); + var ondownloaderrorhandler = aFailOnError ? + function() { + ok(false, "We should not get an error but got " + + lApp.downloadError.name); + PackagedTestHelper.finish(); + } : null; + checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler, - null, true); + ondownloaderrorhandler, true); } @@ -238,12 +246,58 @@ }, function() { info("== TEST == Update packaged app - same package"); - updateApp(false, 3, 3); + updateApp(false, 3, 3, true); }, function() { info("== TEST == Check for Update after getting the same package"); checkForUpdate(false); }, + + function() { + PackagedTestHelper.setAppVersion(5, PackagedTestHelper.next, + /* aDontUpdatePackage */ false, + /* aAllowCancel */ false, + /* aRole */ undefined, + /* aFailOnce */ true); + + }, + function() { + info("== TEST == Update packaged app - fail the update once"); + + var downloadSuccess = function() { + ok(false, "We got an unexpected downloadsuccess or downloadapplied"); + PackagedTestHelper.finish(); + }; + var downloadError = function() { + info("We got an expected download error: " + + PackagedTestHelper.gApp.downloadError.name); + PackagedTestHelper.next(); + }; + checkForUpdate(true, downloadSuccess, downloadSuccess, downloadError, + /* aLaunchDownload */ true); + }, + function() { + info("=== TEST == Update packaged app - apply the update after failing"); + var lApp = PackagedTestHelper.gApp; + lApp.ondownloadsuccess = function() { + info("Download succeeded, applying it"); + navigator.mozApps.mgmt.applyDownload(lApp); + }; + lApp.ondownloadapplied = function() { + info("Download successfuly applied"); + PackagedTestHelper.next(); + }; + lApp.ondownloaderror = function() { + ok(false, "Got an unexpected error: " + lApp.downloaderror.name); + PackagedTestHelper.finish(); + }; + lApp.download(); + }, + function() { + info("== TEST == Check for Update applying a previously failed package"); + checkForUpdate(false); + }, + function() { PackagedTestHelper.setAppVersion(1, PackagedTestHelper.next); }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/Webapps.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/Webapps.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/apps/Webapps.jsm 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/apps/Webapps.jsm 2014-11-26 21:45:54.000000000 +0000 @@ -3263,7 +3263,7 @@ // can proceed to access the app. We also throw an error to alert // the caller that the package wasn't downloaded. this._sendAppliedEvent(aOldApp); - throw new Error("PACKAGE_UNCHANGED"); + throw "PACKAGE_UNCHANGED"; } let newManifest = yield this._openAndReadPackage(zipFile, aOldApp, aNewApp, @@ -3922,6 +3922,13 @@ return; } + // If the error that got us here was that the package hasn't changed, + // since we already sent a success and an applied, let's not confuse + // the clients... + if (aError == "PACKAGE_UNCHANGED") { + return; + } + let download = AppDownloadManager.get(aNewApp.manifestURL); aOldApp.downloading = false; @@ -3933,7 +3940,9 @@ : aIsUpdate ? "installed" : "pending"; - if (aOldApp.staged) { + // Erase the .staged properties only if there's no download available + // anymore. + if (!aOldApp.downloadAvailable && aOldApp.staged) { delete aOldApp.staged; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Console.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Console.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Console.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Console.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -805,6 +805,31 @@ return NS_OK; } +class ConsoleTimelineMarker : public nsDocShell::TimelineMarker +{ +public: + ConsoleTimelineMarker(nsDocShell* aDocShell, + TracingMetadata aMetaData, + const nsAString& aCause) + : nsDocShell::TimelineMarker(aDocShell, "ConsoleTime", aMetaData, aCause) + { + } + + virtual bool Equals(const nsDocShell::TimelineMarker* aOther) + { + if (!nsDocShell::TimelineMarker::Equals(aOther)) { + return false; + } + // Console markers must have matching causes as well. + return GetCause() == aOther->GetCause(); + } + + virtual void AddDetails(mozilla::dom::ProfileTimelineMarker& aMarker) + { + aMarker.mCauseName.Construct(GetCause()); + } +}; + // Queue a call to a console method. See the CALL_DELAY constant. void Console::Method(JSContext* aCx, MethodName aMethodName, @@ -925,7 +950,6 @@ callData->mMonotonicTimer = performance->Now(); // 'time' and 'timeEnd' are displayed in the devtools timeline if active. - // Marked as "ConsoleTime:ARG1". bool isTimelineRecording = false; nsDocShell* docShell = static_cast(mWindow->GetDocShell()); if (docShell) { @@ -938,10 +962,11 @@ if (jsString) { nsAutoJSString key; if (key.init(aCx, jsString)) { - nsCString str("ConsoleTime:"); - AppendUTF16toUTF8(key, str); - docShell->AddProfileTimelineMarker(str.get(), - aMethodName == MethodTime ? TRACING_INTERVAL_START : TRACING_INTERVAL_END); + mozilla::UniquePtr marker = + MakeUnique(docShell, + aMethodName == MethodTime ? TRACING_INTERVAL_START : TRACING_INTERVAL_END, + key); + docShell->AddProfileTimelineMarker(marker); } } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Element.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Element.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Element.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Element.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -25,6 +25,7 @@ #include "nsIDOMDocument.h" #include "nsIContentIterator.h" #include "nsFocusManager.h" +#include "nsFrameManager.h" #include "nsILinkHandler.h" #include "nsIScriptGlobalObject.h" #include "nsIURL.h" @@ -137,6 +138,7 @@ #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/dom/WindowBinding.h" #include "mozilla/dom/ElementBinding.h" +#include "mozilla/dom/VRDevice.h" using namespace mozilla; using namespace mozilla::dom; @@ -976,6 +978,7 @@ nsIPresShell* shell = doc->GetShell(); if (shell) { shell->DestroyFramesFor(this, &destroyedFramesFor); + MOZ_ASSERT(!shell->FrameManager()->GetDisplayContentsStyleFor(this)); } } MOZ_ASSERT(!GetPrimaryFrame()); @@ -1469,7 +1472,17 @@ NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES | // And the restyle bits ELEMENT_ALL_RESTYLE_FLAGS); - } else if (!IsInShadowTree()) { + } else if (IsInShadowTree()) { + // We're not in a document, but we did get inserted into a shadow tree. + // Since we won't have any restyle data in the document's restyle trackers, + // don't let us get inserted with restyle bits set incorrectly. + // + // Also clear all the other flags that are cleared above when we do get + // inserted into a document. + UnsetFlags(NODE_FORCE_XBL_BINDINGS | + NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES | + ELEMENT_ALL_RESTYLE_FLAGS); + } else { // If we're not in the doc and not in a shadow tree, // update our subtree pointer. SetSubtreeRootPointer(aParent->SubtreeRoot()); @@ -3061,7 +3074,7 @@ } void -Element::MozRequestFullScreen() +Element::MozRequestFullScreen(const RequestFullscreenOptions& aOptions) { // Only grant full-screen requests if this is called from inside a trusted // event handler (i.e. inside an event handler for a user initiated event). @@ -3085,7 +3098,12 @@ return; } - OwnerDoc()->AsyncRequestFullScreen(this); + FullScreenOptions opts; + if (aOptions.mVrDisplay) { + opts.mVRHMDDevice = aOptions.mVrDisplay->GetHMD(); + } + + OwnerDoc()->AsyncRequestFullScreen(this, opts); return; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Element.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Element.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Element.h 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Element.h 2014-11-26 21:45:55.000000000 +0000 @@ -34,6 +34,7 @@ #include "mozilla/EventForwards.h" #include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/WindowBinding.h" +#include "mozilla/dom/ElementBinding.h" #include "Units.h" class nsIDOMEventListener; @@ -724,7 +725,7 @@ nsIPresShell::SetCapturingContent(nullptr, 0); } } - void MozRequestFullScreen(); + void MozRequestFullScreen(const RequestFullscreenOptions& aOptions); void MozRequestPointerLock(); Attr* GetAttributeNode(const nsAString& aName); already_AddRefed SetAttributeNode(Attr& aNewAttr, @@ -1768,7 +1769,7 @@ } \ NS_IMETHOD MozRequestFullScreen(void) MOZ_FINAL \ { \ - Element::MozRequestFullScreen(); \ + Element::MozRequestFullScreen(mozilla::dom::RequestFullscreenOptions()); \ return NS_OK; \ } \ NS_IMETHOD MozRequestPointerLock(void) MOZ_FINAL \ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/EventSource.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/EventSource.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/EventSource.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/EventSource.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -62,7 +62,6 @@ mGoingToDispatchAllMessages(false), mWithCredentials(false), mWaitingForOnStopRequest(false), - mInterrupted(false), mLastConvertionResult(NS_OK), mReadyState(CONNECTING), mScriptLine(0), @@ -341,21 +340,14 @@ nsCOMPtr httpChannel = do_QueryInterface(aRequest, &rv); NS_ENSURE_SUCCESS(rv, rv); - bool requestSucceeded; - rv = httpChannel->GetRequestSucceeded(&requestSucceeded); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString contentType; - rv = httpChannel->GetContentType(contentType); - NS_ENSURE_SUCCESS(rv, rv); - nsresult status; - aRequest->GetStatus(&status); + rv = aRequest->GetStatus(&status); + NS_ENSURE_SUCCESS(rv, rv); - if (NS_FAILED(status) || !requestSucceeded || - !contentType.EqualsLiteral(TEXT_EVENT_STREAM)) { - DispatchFailConnection(); - return NS_ERROR_NOT_AVAILABLE; + if (NS_FAILED(status)) { + // EventSource::OnStopRequest will evaluate if it shall either reestablish + // or fail the connection + return NS_ERROR_ABORT; } uint32_t httpStatus; @@ -363,7 +355,15 @@ NS_ENSURE_SUCCESS(rv, rv); if (httpStatus != 200) { - mInterrupted = true; + DispatchFailConnection(); + return NS_ERROR_ABORT; + } + + nsAutoCString contentType; + rv = httpChannel->GetContentType(contentType); + NS_ENSURE_SUCCESS(rv, rv); + + if (!contentType.EqualsLiteral(TEXT_EVENT_STREAM)) { DispatchFailConnection(); return NS_ERROR_ABORT; } @@ -454,19 +454,27 @@ return NS_ERROR_ABORT; } - if (NS_FAILED(aStatusCode)) { + // "Network errors that prevents the connection from being established in the + // first place (e.g. DNS errors), must cause the user agent to asynchronously + // reestablish the connection. + // + // (...) the cancelation of the fetch algorithm by the user agent (e.g. in + // response to window.stop() or the user canceling the network connection + // manually) must cause the user agent to fail the connection. + + if (NS_FAILED(aStatusCode) && + aStatusCode != NS_ERROR_CONNECTION_REFUSED && + aStatusCode != NS_ERROR_NET_TIMEOUT && + aStatusCode != NS_ERROR_NET_RESET && + aStatusCode != NS_ERROR_NET_INTERRUPT && + aStatusCode != NS_ERROR_PROXY_CONNECTION_REFUSED && + aStatusCode != NS_ERROR_DNS_LOOKUP_QUEUE_FULL) { DispatchFailConnection(); - return aStatusCode; + return NS_ERROR_ABORT; } - nsresult rv; - nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest); - if (NS_SUCCEEDED(healthOfRequestResult) && - mLastConvertionResult == NS_PARTIAL_MORE_INPUT) { - // we had an incomplete UTF8 char at the end of the stream - rv = ParseCharacter(REPLACEMENT_CHAR); - NS_ENSURE_SUCCESS(rv, rv); - } + nsresult rv = CheckHealthOfRequestCallback(aRequest); + NS_ENSURE_SUCCESS(rv, rv); ClearFields(); @@ -477,7 +485,7 @@ rv = NS_DispatchToMainThread(event); NS_ENSURE_SUCCESS(rv, rv); - return healthOfRequestResult; + return NS_OK; } /** @@ -692,6 +700,17 @@ return NS_OK; } +net::ReferrerPolicy +EventSource::GetReferrerPolicy() +{ + nsresult rv; + nsIScriptContext* sc = GetContextForEventHandlers(&rv); + NS_ENSURE_SUCCESS(rv, mozilla::net::RP_Default); + + nsCOMPtr doc = nsContentUtils::GetDocumentFromScriptContext(sc); + return doc ? doc->GetReferrerPolicy() : mozilla::net::RP_Default; +} + nsresult EventSource::SetupHttpChannel() { @@ -712,7 +731,7 @@ nsCOMPtr codebase; nsresult rv = GetBaseURI(getter_AddRefs(codebase)); if (NS_SUCCEEDED(rv)) { - rv = mHttpChannel->SetReferrer(codebase); + rv = mHttpChannel->SetReferrerWithPolicy(codebase, this->GetReferrerPolicy()); NS_ENSURE_SUCCESS(rv, rv); } @@ -869,11 +888,6 @@ return; } - if (mReadyState != OPEN) { - NS_WARNING("Unexpected mReadyState!!!"); - return; - } - nsresult rv = ResetConnection(); if (NS_FAILED(rv)) { NS_WARNING("Failed to reset the connection!!!"); @@ -994,7 +1008,7 @@ NS_ConvertUTF8toUTF16 specUTF16(targetSpec); const char16_t *formatStrings[] = { specUTF16.get() }; - if (mReadyState == CONNECTING && !mInterrupted) { + if (mReadyState == CONNECTING) { rv = PrintErrorOnConsole("chrome://global/locale/appstrings.properties", MOZ_UTF16("connectionFailure"), formatStrings, ArrayLength(formatStrings)); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/EventSource.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/EventSource.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/EventSource.h 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/EventSource.h 2014-11-26 21:45:55.000000000 +0000 @@ -109,6 +109,8 @@ nsresult GetBaseURI(nsIURI **aBaseURI); + net::ReferrerPolicy GetReferrerPolicy(); + nsresult SetupHttpChannel(); nsresult InitChannelAndRequestEventSource(); nsresult ResetConnection(); @@ -221,7 +223,6 @@ bool mGoingToDispatchAllMessages; bool mWithCredentials; bool mWaitingForOnStopRequest; - bool mInterrupted; // used while reading the input streams nsCOMPtr mUnicodeDecoder; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Navigator.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Navigator.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Navigator.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Navigator.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -40,6 +40,7 @@ #include "mozilla/dom/Telephony.h" #include "mozilla/dom/Voicemail.h" #include "mozilla/dom/TVManager.h" +#include "mozilla/dom/VRDevice.h" #include "mozilla/Hal.h" #include "nsISiteSpecificUserAgent.h" #include "mozilla/ClearOnShutdown.h" @@ -1722,6 +1723,32 @@ } #endif +already_AddRefed +Navigator::GetVRDevices(ErrorResult& aRv) +{ + if (!mWindow || !mWindow->GetDocShell()) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + nsCOMPtr go = do_QueryInterface(mWindow); + nsRefPtr p = Promise::Create(go, aRv); + if (aRv.Failed()) { + return nullptr; + } + + nsGlobalWindow* win = static_cast(mWindow.get()); + + nsTArray> vrDevs; + if (!win->GetVRDevices(vrDevs)) { + p->MaybeReject(NS_ERROR_FAILURE); + } else { + p->MaybeResolve(vrDevs); + } + + return p.forget(); +} + //***************************************************************************** // Navigator::nsIMozNavigatorNetwork //***************************************************************************** @@ -2533,5 +2560,43 @@ return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent); } +#ifdef MOZ_EME +already_AddRefed +Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem, + const Optional>& aOptions, + ErrorResult& aRv) +{ + nsCOMPtr go = do_QueryInterface(mWindow); + nsRefPtr p = Promise::Create(go, aRv); + if (aRv.Failed()) { + return nullptr; + } + + if (aKeySystem.IsEmpty() || + (aOptions.WasPassed() && aOptions.Value().IsEmpty())) { + p->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); + return p.forget(); + } + + if (!MediaKeySystemAccess::IsKeySystemSupported(aKeySystem)) { + p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return p.forget(); + } + + // TODO: Wait (async) until the CDM is downloaded, if it's not already. + + if (!aOptions.WasPassed() || + MediaKeySystemAccess::IsSupported(aKeySystem, aOptions.Value())) { + nsRefPtr access(new MediaKeySystemAccess(mWindow, aKeySystem)); + p->MaybeResolve(access); + return p.forget(); + } + + p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + + return p.forget(); +} +#endif + } // namespace dom } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Navigator.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Navigator.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/Navigator.h 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/Navigator.h 2014-11-26 21:45:55.000000000 +0000 @@ -18,6 +18,9 @@ #include "nsInterfaceHashtable.h" #include "nsString.h" #include "nsTArray.h" +#ifdef MOZ_EME +#include "mozilla/dom/MediaKeySystemAccess.h" +#endif class nsPluginArray; class nsMimeTypeArray; @@ -243,6 +246,7 @@ #ifdef MOZ_GAMEPAD void GetGamepads(nsTArray >& aGamepads, ErrorResult& aRv); #endif // MOZ_GAMEPAD + already_AddRefed GetVRDevices(ErrorResult& aRv); #ifdef MOZ_B2G_FM FMRadio* GetMozFMRadio(ErrorResult& aRv); #endif @@ -316,6 +320,13 @@ virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; +#ifdef MOZ_EME + already_AddRefed + RequestMediaKeySystemAccess(const nsAString& aKeySystem, + const Optional>& aOptions, + ErrorResult& aRv); +#endif + private: virtual ~Navigator(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentAreaDragDrop.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentAreaDragDrop.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentAreaDragDrop.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentAreaDragDrop.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -158,7 +158,10 @@ persist->SetPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION); - return persist->SavePrivacyAwareURI(sourceURI, nullptr, nullptr, nullptr, nullptr, + // referrer policy can be anything since the referrer is nullptr + return persist->SavePrivacyAwareURI(sourceURI, nullptr, nullptr, + mozilla::net::RP_Default, + nullptr, nullptr, inDestFile, isPrivate); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentSink.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentSink.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentSink.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentSink.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -736,7 +736,7 @@ // We don't support CORS for processing instructions bool isAlternate; rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate, - CORS_NONE, + CORS_NONE, mDocument->GetReferrerPolicy(), mRunsToCompletion ? nullptr : this, &isAlternate); NS_ENSURE_SUCCESS(rv, rv); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentUtils.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentUtils.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentUtils.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentUtils.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -2985,6 +2985,7 @@ nsresult nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer, + net::ReferrerPolicy aReferrerPolicy, imgINotificationObserver* aObserver, int32_t aLoadFlags, const nsAString& initiatorType, imgRequestProxy** aRequest, @@ -3016,6 +3017,7 @@ return imgLoader->LoadImage(aURI, /* uri to load */ documentURI, /* initialDocumentURI */ aReferrer, /* referrer */ + aReferrerPolicy, /* referrer policy */ aLoadingPrincipal, /* loading principal */ loadGroup, /* loadgroup */ aObserver, /* imgINotificationObserver */ @@ -5749,6 +5751,23 @@ { NS_PRECONDITION(aURI, "missing uri"); + // For Blob URI we have to return the origin of page using its principal. + nsCOMPtr uriWithPrincipal = do_QueryInterface(aURI); + if (uriWithPrincipal) { + nsCOMPtr principal; + uriWithPrincipal->GetPrincipal(getter_AddRefs(principal)); + + if (principal) { + nsCOMPtr uri; + nsresult rv = principal->GetURI(getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + + if (uri && uri != aURI) { + return GetASCIIOrigin(uri, aOrigin); + } + } + } + aOrigin.Truncate(); nsCOMPtr uri = NS_GetInnermostURI(aURI); @@ -5807,6 +5826,23 @@ { NS_PRECONDITION(aURI, "missing uri"); + // For Blob URI we have to return the origin of page using its principal. + nsCOMPtr uriWithPrincipal = do_QueryInterface(aURI); + if (uriWithPrincipal) { + nsCOMPtr principal; + uriWithPrincipal->GetPrincipal(getter_AddRefs(principal)); + + if (principal) { + nsCOMPtr uri; + nsresult rv = principal->GetURI(getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + + if (uri && uri != aURI) { + return GetUTFOrigin(uri, aOrigin); + } + } + } + aOrigin.Truncate(); nsCOMPtr uri = NS_GetInnermostURI(aURI); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentUtils.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentUtils.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsContentUtils.h 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsContentUtils.h 2014-11-26 21:45:55.000000000 +0000 @@ -30,6 +30,7 @@ #include "mozilla/dom/AutocompleteInfoBinding.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/FloatingPoint.h" +#include "mozilla/net/ReferrerPolicy.h" #include "nsIContentPolicy.h" #if defined(XP_WIN) @@ -619,6 +620,8 @@ * @param aLoadingDocument the document we belong to * @param aLoadingPrincipal the principal doing the load * @param aReferrer the referrer URI + * @param aReferrerPolicy the referrer-sending policy to use on channel + * creation * @param aObserver the observer for the image load * @param aLoadFlags the load flags to use. See nsIRequest * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) @@ -629,6 +632,7 @@ nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer, + mozilla::net::ReferrerPolicy aReferrerPolicy, imgINotificationObserver* aObserver, int32_t aLoadFlags, const nsAString& initiatorType, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsCrossSiteListenerProxy.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsCrossSiteListenerProxy.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsCrossSiteListenerProxy.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsCrossSiteListenerProxy.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -1127,15 +1127,14 @@ loadFlags); } else { - rv = NS_NewChannelInternal(getter_AddRefs(preflightChannel), - uri, - nullptr, // aRequestingNode, - nsContentUtils::GetSystemPrincipal(), - nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_OTHER, - loadGroup, - nullptr, // aCallbacks - loadFlags); + rv = NS_NewChannel(getter_AddRefs(preflightChannel), + uri, + nsContentUtils::GetSystemPrincipal(), + nsILoadInfo::SEC_NORMAL, + nsIContentPolicy::TYPE_OTHER, + loadGroup, + nullptr, // aCallbacks + loadFlags); } NS_ENSURE_SUCCESS(rv, rv); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDocument.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDocument.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDocument.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDocument.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -190,6 +190,7 @@ #include "mozilla/dom/Event.h" #include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLInputElement.h" +#include "mozilla/dom/MediaQueryList.h" #include "mozilla/dom/NodeFilterBinding.h" #include "mozilla/dom/OwningNonNull.h" #include "mozilla/dom/TabChild.h" @@ -1539,6 +1540,8 @@ // ================================================================== nsIDocument::nsIDocument() : nsINode(nullNodeInfo), + mReferrerPolicySet(false), + mReferrerPolicy(mozilla::net::RP_Default), mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")), mNodeInfoManager(nullptr), mCompatMode(eCompatibility_FullStandards), @@ -1558,6 +1561,8 @@ mDidFireDOMContentLoaded(true) { SetInDocument(); + + PR_INIT_CLIST(&mDOMMediaQueryLists); } // NOTE! nsDocument::operator new() zeroes out all members, so don't @@ -1603,6 +1608,9 @@ nsIDocument::~nsIDocument() { + NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists), + "must not have media query lists left"); + if (mNodeInfoManager) { mNodeInfoManager->DropDocumentReference(); } @@ -2016,6 +2024,18 @@ for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) { nsHostObjectProtocolHandler::Traverse(tmp->mHostObjectURIs[i], cb); } + + // We own only the items in mDOMMediaQueryLists that have listeners; + // this reference is managed by their AddListener and RemoveListener + // methods. + for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists); + l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) { + MediaQueryList *mql = static_cast(l); + if (mql->HasListeners()) { + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item"); + cb.NoteXPCOMChild(mql); + } + } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument) @@ -2118,6 +2138,17 @@ nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i]); } + // We own only the items in mDOMMediaQueryLists that have listeners; + // this reference is managed by their AddListener and RemoveListener + // methods. + for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists); + l != &tmp->mDOMMediaQueryLists; ) { + PRCList *next = PR_NEXT_LINK(l); + MediaQueryList *mql = static_cast(l); + mql->RemoveAllListeners(); + l = next; + } + tmp->mInUnlinkOrDeletion = false; NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -3701,6 +3732,20 @@ aHeaderField == nsGkAtoms::viewport_user_scalable) { mViewportType = Unknown; } + + // Referrer policy spec says to ignore any empty referrer policies. + if (aHeaderField == nsGkAtoms::referrer && !aData.IsEmpty()) { + ReferrerPolicy policy = mozilla::net::ReferrerPolicyFromString(aData); + + // Referrer policy spec (section 6.1) says that once the referrer policy + // is set, any future attempts to change it result in No-Referrer. + if (!mReferrerPolicySet) { + mReferrerPolicy = policy; + mReferrerPolicySet = true; + } else if (mReferrerPolicy != policy) { + mReferrerPolicy = mozilla::net::RP_No_Referrer; + } + } } void @@ -6012,127 +6057,147 @@ rv.Throw(NS_ERROR_UNEXPECTED); return; } - JS::Rooted global(aCx, sgo->GetGlobalJSObject()); - - JSAutoCompartment ac(aCx, global); - - JS::Handle htmlProto( - HTMLElementBinding::GetProtoObjectHandle(aCx, global)); - if (!htmlProto) { - rv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } + JS::Rooted global(aCx, sgo->GetGlobalJSObject()); + nsCOMPtr nameAtom;; int32_t namespaceID = kNameSpaceID_XHTML; JS::Rooted protoObject(aCx); - if (!aOptions.mPrototype) { - protoObject = JS_NewObject(aCx, nullptr, htmlProto, JS::NullPtr()); - if (!protoObject) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } - } else { - // If a prototype is provided, we must check to ensure that it is from the - // same browsing context as us. - protoObject = aOptions.mPrototype; - if (JS_GetGlobalForObject(aCx, protoObject) != global) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } + { + JSAutoCompartment ac(aCx, global); - // If PROTOTYPE is already an interface prototype object for any interface - // object or PROTOTYPE has a non-configurable property named constructor, - // throw a NotSupportedError and stop. - const js::Class* clasp = js::GetObjectClass(protoObject); - if (IsDOMIfaceAndProtoClass(clasp)) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + JS::Handle htmlProto( + HTMLElementBinding::GetProtoObjectHandle(aCx, global)); + if (!htmlProto) { + rv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } - JS::Rooted descRoot(aCx); - JS::MutableHandle desc(&descRoot); - if (!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", desc)) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } + if (!aOptions.mPrototype) { + protoObject = JS_NewObject(aCx, nullptr, htmlProto, JS::NullPtr()); + if (!protoObject) { + rv.Throw(NS_ERROR_UNEXPECTED); + return; + } + } else { + protoObject = aOptions.mPrototype; - // Check if non-configurable - if (desc.isPermanent()) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } + // We are already operating on the document's (/global's) compartment. Let's + // get a view of the passed in proto from this compartment. + if (!JS_WrapObject(aCx, &protoObject)) { + rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } - JS::Handle svgProto( - SVGElementBinding::GetProtoObjectHandle(aCx, global)); - if (!svgProto) { - rv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } + // We also need an unwrapped version of it for various checks. + JS::Rooted protoObjectUnwrapped(aCx, + js::CheckedUnwrap(protoObject)); + if (!protoObjectUnwrapped) { + // If the documents compartment does not have same origin access + // to the compartment of the proto we should just throw. + rv.Throw(NS_ERROR_DOM_SECURITY_ERR); + return; + } - JS::Rooted protoProto(aCx, protoObject); + // If PROTOTYPE is already an interface prototype object for any interface + // object or PROTOTYPE has a non-configurable property named constructor, + // throw a NotSupportedError and stop. + const js::Class* clasp = js::GetObjectClass(protoObjectUnwrapped); + if (IsDOMIfaceAndProtoClass(clasp)) { + rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } - // If PROTOTYPE's interface inherits from SVGElement, set NAMESPACE to SVG - // Namespace. - while (protoProto) { - if (protoProto == htmlProto) { - break; + JS::Rooted descRoot(aCx); + JS::MutableHandle desc(&descRoot); + // This check will go through a wrapper, but as we checked above + // it should be transparent or an xray. This should be fine for now, + // until the spec is sorted out. + if (!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", desc)) { + rv.Throw(NS_ERROR_UNEXPECTED); + return; } - if (protoProto == svgProto) { - namespaceID = kNameSpaceID_SVG; - break; + // Check if non-configurable + if (desc.isPermanent()) { + rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; } - if (!JS_GetPrototype(aCx, protoProto, &protoProto)) { - rv.Throw(NS_ERROR_UNEXPECTED); + JS::Handle svgProto( + SVGElementBinding::GetProtoObjectHandle(aCx, global)); + if (!svgProto) { + rv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } + + JS::Rooted protoProto(aCx, protoObject); + + // If PROTOTYPE's interface inherits from SVGElement, set NAMESPACE to SVG + // Namespace. + while (protoProto) { + if (protoProto == htmlProto) { + break; + } + + if (protoProto == svgProto) { + namespaceID = kNameSpaceID_SVG; + break; + } + + if (!JS_GetPrototype(aCx, protoProto, &protoProto)) { + rv.Throw(NS_ERROR_UNEXPECTED); + return; + } + } } - } - // If name was provided and not null... - nsCOMPtr nameAtom; - if (!lcName.IsEmpty()) { - // Let BASE be the element interface for NAME and NAMESPACE. - bool known = false; - nameAtom = do_GetAtom(lcName); - if (namespaceID == kNameSpaceID_XHTML) { - nsIParserService* ps = nsContentUtils::GetParserService(); - if (!ps) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; + // If name was provided and not null... + if (!lcName.IsEmpty()) { + // Let BASE be the element interface for NAME and NAMESPACE. + bool known = false; + nameAtom = do_GetAtom(lcName); + if (namespaceID == kNameSpaceID_XHTML) { + nsIParserService* ps = nsContentUtils::GetParserService(); + if (!ps) { + rv.Throw(NS_ERROR_UNEXPECTED); + return; + } + + known = + ps->HTMLCaseSensitiveAtomTagToId(nameAtom) != eHTMLTag_userdefined; + } else { + known = SVGElementFactory::Exists(nameAtom); } - known = - ps->HTMLCaseSensitiveAtomTagToId(nameAtom) != eHTMLTag_userdefined; + // If BASE does not exist or is an interface for a custom element, set ERROR + // to InvalidName and stop. + // If BASE exists, then it cannot be an interface for a custom element. + if (!known) { + rv.Throw(NS_ERROR_DOM_SYNTAX_ERR); + return; + } } else { - known = SVGElementFactory::Exists(nameAtom); - } + // If NAMESPACE is SVG Namespace, set ERROR to InvalidName and stop. + if (namespaceID == kNameSpaceID_SVG) { + rv.Throw(NS_ERROR_UNEXPECTED); + return; + } - // If BASE does not exist or is an interface for a custom element, set ERROR - // to InvalidName and stop. - // If BASE exists, then it cannot be an interface for a custom element. - if (!known) { - rv.Throw(NS_ERROR_DOM_SYNTAX_ERR); - return; - } - } else { - // If NAMESPACE is SVG Namespace, set ERROR to InvalidName and stop. - if (namespaceID == kNameSpaceID_SVG) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; + nameAtom = typeAtom; } + } // Leaving the document's compartment for the LifecycleCallbacks init - nameAtom = typeAtom; - } - + // Note: We call the init from the caller compartment here nsAutoPtr callbacksHolder(new LifecycleCallbacks()); JS::RootedValue rootedv(aCx, JS::ObjectValue(*protoObject)); - if (!callbacksHolder->Init(aCx, rootedv)) { + if (!JS_WrapValue(aCx, &rootedv) || !callbacksHolder->Init(aCx, rootedv)) { rv.Throw(NS_ERROR_FAILURE); return; } + // Entering the global's compartment again + JSAutoCompartment ac(aCx, global); + // Associate the definition with the custom element. CustomElementHashKey key(namespaceID, typeAtom); LifecycleCallbacks* callbacks = callbacksHolder.forget(); @@ -7103,6 +7168,17 @@ } } +already_AddRefed +nsIDocument::MatchMedia(const nsAString& aMediaQueryList) +{ + nsRefPtr result = new MediaQueryList(this, aMediaQueryList); + + // Insert the new item at the end of the linked list. + PR_INSERT_BEFORE(result, &mDOMMediaQueryLists); + + return result.forget(); +} + void nsDocument::FlushSkinBindings() { @@ -7682,6 +7758,13 @@ CSSToScreenScale defaultScale = layoutDeviceScale * LayoutDeviceToScreenScale(1.0); + if (!Preferences::GetBool("dom.meta-viewport.enabled", false)) { + return nsViewportInfo(aDisplaySize, + defaultScale, + /*allowZoom*/ false, + /*allowDoubleTapZoom*/ true); + } + // In cases where the width of the CSS viewport is less than or equal to the width // of the display (i.e. width <= device-width) then we disable double-tap-to-zoom // behaviour. See bug 941995 for details. @@ -9465,7 +9548,8 @@ } void -nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr) +nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, + ReferrerPolicy aReferrerPolicy) { // Early exit if the img is already present in the img-cache // which indicates that the "real" load has already started and @@ -9499,6 +9583,7 @@ this, NodePrincipal(), mDocumentURI, // uri of document used as referrer + aReferrerPolicy, nullptr, // no observer loadFlags, NS_LITERAL_STRING("img"), @@ -9508,7 +9593,22 @@ // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and // unlink if (NS_SUCCEEDED(rv)) { - mPreloadingImages.AppendObject(request); + mPreloadingImages.Put(uri, request.forget()); + } +} + +void +nsDocument::ForgetImagePreload(nsIURI* aURI) +{ + // Checking count is faster than hashing the URI in the common + // case of empty table. + if (mPreloadingImages.Count() != 0) { + nsCOMPtr req; + mPreloadingImages.Remove(aURI, getter_AddRefs(req)); + if (req) { + // Make sure to cancel the request so imagelib knows it's gone. + req->CancelAndForgetObserver(NS_BINDING_ABORTED); + } } } @@ -9554,7 +9654,8 @@ void nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset, - const nsAString& aCrossOriginAttr) + const nsAString& aCrossOriginAttr, + const ReferrerPolicy aReferrerPolicy) { // The CSSLoader will retain this object after we return. nsCOMPtr obs = new StubCSSLoaderObserver(); @@ -9563,7 +9664,8 @@ CSSLoader()->LoadSheet(uri, NodePrincipal(), NS_LossyConvertUTF16toASCII(charset), obs, - Element::StringToCORSMode(aCrossOriginAttr)); + Element::StringToCORSMode(aCrossOriginAttr), + aReferrerPolicy); } nsresult @@ -10650,13 +10752,13 @@ // Element::UnbindFromTree(). class nsSetWindowFullScreen : public nsRunnable { public: - nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue) - : mDoc(aDoc), mValue(aValue) {} + nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo* aHMD = nullptr) + : mDoc(aDoc), mValue(aValue), mHMD(aHMD) {} NS_IMETHOD Run() { if (mDoc->GetWindow()) { - mDoc->GetWindow()->SetFullScreenInternal(mValue, false); + mDoc->GetWindow()->SetFullScreenInternal(mValue, false, mHMD); } return NS_OK; } @@ -10664,6 +10766,7 @@ private: nsCOMPtr mDoc; bool mValue; + nsRefPtr mHMD; }; static nsIDocument* @@ -10683,7 +10786,7 @@ } static void -SetWindowFullScreen(nsIDocument* aDoc, bool aValue) +SetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo *aVRHMD = nullptr) { // Maintain list of fullscreen root documents. nsCOMPtr root = GetFullscreenRootDocument(aDoc); @@ -10693,7 +10796,7 @@ FullscreenRoots::Remove(root); } if (!nsContentUtils::IsFullscreenApiContentOnly()) { - nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue)); + nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue, aVRHMD)); } } @@ -11013,12 +11116,13 @@ class nsCallRequestFullScreen : public nsRunnable { public: - explicit nsCallRequestFullScreen(Element* aElement) + explicit nsCallRequestFullScreen(Element* aElement, FullScreenOptions& aOptions) : mElement(aElement), mDoc(aElement->OwnerDoc()), mWasCallerChrome(nsContentUtils::IsCallerChrome()), mHadRequestPending(static_cast(mDoc.get())-> - mAsyncFullscreenPending) + mAsyncFullscreenPending), + mOptions(aOptions) { static_cast(mDoc.get())-> mAsyncFullscreenPending = true; @@ -11030,6 +11134,7 @@ mAsyncFullscreenPending = mHadRequestPending; nsDocument* doc = static_cast(mDoc.get()); doc->RequestFullScreen(mElement, + mOptions, mWasCallerChrome, /* aNotifyOnOriginChange */ true); return NS_OK; @@ -11039,10 +11144,12 @@ nsCOMPtr mDoc; bool mWasCallerChrome; bool mHadRequestPending; + FullScreenOptions mOptions; }; void -nsDocument::AsyncRequestFullScreen(Element* aElement) +nsDocument::AsyncRequestFullScreen(Element* aElement, + FullScreenOptions& aOptions) { NS_ASSERTION(aElement, "Must pass non-null element to nsDocument::AsyncRequestFullScreen"); @@ -11050,7 +11157,7 @@ return; } // Request full-screen asynchronously. - nsCOMPtr event(new nsCallRequestFullScreen(aElement)); + nsCOMPtr event(new nsCallRequestFullScreen(aElement, aOptions)); NS_DispatchToCurrentThread(event); } @@ -11118,6 +11225,9 @@ Element* top = FullScreenStackTop(); NS_ASSERTION(top, "Should have a top when full-screen stack isn't empty"); if (top) { + // Remove any VR state properties + top->DeleteProperty(nsGkAtoms::vr_state); + EventStateManager::SetFullScreenState(top, false); } mFullScreenStack.Clear(); @@ -11154,8 +11264,12 @@ return; } - // Remove styles from existing top element. Element* top = FullScreenStackTop(); + + // Remove any VR state properties + top->DeleteProperty(nsGkAtoms::vr_state); + + // Remove styles from existing top element. EventStateManager::SetFullScreenState(top, false); // Remove top element. Note the remaining top element in the stack @@ -11243,7 +11357,9 @@ // If the frame element is already the fullscreen element in this document, // this has no effect. nsCOMPtr content(do_QueryInterface(aFrameElement)); + FullScreenOptions opts; RequestFullScreen(content->AsElement(), + opts, /* aWasCallerChrome */ false, /* aNotifyOnOriginChange */ false); @@ -11269,8 +11385,17 @@ return NS_OK; } +static void +ReleaseHMDInfoRef(void *, nsIAtom*, void *aPropertyValue, void *) +{ + if (aPropertyValue) { + static_cast(aPropertyValue)->Release(); + } +} + void nsDocument::RequestFullScreen(Element* aElement, + FullScreenOptions& aOptions, bool aWasCallerChrome, bool aNotifyOnOriginChange) { @@ -11359,6 +11484,14 @@ UnlockPointer(); } + // Process options -- in this case, just HMD + if (aOptions.mVRHMDDevice) { + nsRefPtr hmdRef = aOptions.mVRHMDDevice; + aElement->SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(), + ReleaseHMDInfoRef, + true); + } + // Set the full-screen element. This sets the full-screen style on the // element, and the full-screen-ancestor styles on ancestors of the element // in this document. @@ -11463,7 +11596,7 @@ // modes. Also note that nsGlobalWindow::SetFullScreen() (which // SetWindowFullScreen() calls) proxies to the root window in its hierarchy, // and does not operate on the a per-nsIDOMWindow basis. - SetWindowFullScreen(this, true); + SetWindowFullScreen(this, true, aOptions.mVRHMDDevice); } NS_IMETHODIMP diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDocument.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDocument.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDocument.h 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDocument.h 2014-11-26 21:45:55.000000000 +0000 @@ -120,6 +120,7 @@ { public: typedef mozilla::dom::Element Element; + typedef mozilla::net::ReferrerPolicy ReferrerPolicy; explicit nsIdentifierMapEntry(const nsAString& aKey) : nsStringHashKey(&aKey), mNameContentList(nullptr) @@ -1091,10 +1092,13 @@ void MaybeEndOutermostXBLUpdate(); virtual void MaybePreLoadImage(nsIURI* uri, - const nsAString &aCrossOriginAttr) MOZ_OVERRIDE; + const nsAString &aCrossOriginAttr, + ReferrerPolicy aReferrerPolicy) MOZ_OVERRIDE; + virtual void ForgetImagePreload(nsIURI* aURI) MOZ_OVERRIDE; virtual void PreloadStyle(nsIURI* uri, const nsAString& charset, - const nsAString& aCrossOriginAttr) MOZ_OVERRIDE; + const nsAString& aCrossOriginAttr, + ReferrerPolicy aReferrerPolicy) MOZ_OVERRIDE; virtual nsresult LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet, mozilla::CSSStyleSheet** sheet) MOZ_OVERRIDE; @@ -1143,7 +1147,8 @@ virtual Element* FindImageMap(const nsAString& aNormalizedMapName) MOZ_OVERRIDE; virtual Element* GetFullScreenElement() MOZ_OVERRIDE; - virtual void AsyncRequestFullScreen(Element* aElement) MOZ_OVERRIDE; + virtual void AsyncRequestFullScreen(Element* aElement, + mozilla::dom::FullScreenOptions& aOptions) MOZ_OVERRIDE; virtual void RestorePreviousFullScreenState() MOZ_OVERRIDE; virtual bool IsFullscreenLeaf() MOZ_OVERRIDE; virtual bool IsFullScreenDoc() MOZ_OVERRIDE; @@ -1194,6 +1199,7 @@ // need to send the notification with the origin of the document which // originally requested fullscreen, not *this* document's origin. void RequestFullScreen(Element* aElement, + mozilla::dom::FullScreenOptions& aOptions, bool aWasCallerChrome, bool aNotifyOnOriginChange); @@ -1737,8 +1743,11 @@ nsExternalResourceMap mExternalResourceMap; - // All images in process of being preloaded - nsCOMArray mPreloadingImages; + // All images in process of being preloaded. This is a hashtable so + // we can remove them as the real image loads start; that way we + // make sure to not keep the image load going when no one cares + // about it anymore. + nsRefPtrHashtable mPreloadingImages; nsRefPtr mDOMImplementation; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDOMClassInfo.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDOMClassInfo.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDOMClassInfo.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDOMClassInfo.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -108,7 +108,6 @@ #include "FMRadio.h" #endif -#include "nsIDOMGlobalObjectConstructor.h" #include "nsDebug.h" #include "mozilla/dom/BindingUtils.h" @@ -1351,65 +1350,6 @@ return rv; } - nsCOMPtr constructor(do_QueryInterface(native)); - if (constructor) { - // Initialize object using the current inner window, but only if - // the caller can access it. - nsCOMPtr owner = do_QueryReferent(aWeakOwner); - nsPIDOMWindow* outerWindow = owner ? owner->GetOuterWindow() : nullptr; - nsPIDOMWindow* currentInner = - outerWindow ? outerWindow->GetCurrentInnerWindow() : nullptr; - if (!currentInner || - (owner != currentInner && - !nsContentUtils::CanCallerAccess(currentInner))) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - nsCOMPtr wrappedJS = do_QueryInterface(native); - - JS::Rooted thisObject(cx, wrappedJS->GetJSObject()); - if (!thisObject) { - return NS_ERROR_UNEXPECTED; - } - - JSAutoCompartment ac(cx, thisObject); - - JS::Rooted funval(cx); - if (!JS_GetProperty(cx, thisObject, "constructor", &funval) || - !funval.isObject()) { - return NS_ERROR_UNEXPECTED; - } - - // Check if the object is even callable. - NS_ENSURE_STATE(JS::IsCallable(&funval.toObject())); - { - // wrap parameters in the target compartment - // we also pass in the calling window as the first argument - unsigned argc = args.length() + 1; - JS::AutoValueVector argv(cx); - if (!argv.resize(argc)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - nsCOMPtr currentWin(do_GetInterface(currentInner)); - rv = WrapNative(cx, currentWin, &NS_GET_IID(nsIDOMWindow), - true, argv[0]); - - for (size_t i = 1; i < argc; ++i) { - argv[i].set(args[i - 1]); - if (!JS_WrapValue(cx, argv[i])) - return NS_ERROR_FAILURE; - } - - JS::Rooted frval(cx); - bool ret = JS_CallFunctionValue(cx, thisObject, funval, argv, &frval); - - if (!ret) { - return NS_ERROR_FAILURE; - } - } - } - js::AssertSameCompartment(cx, obj); return WrapNative(cx, native, true, args.rval()); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDOMWindowUtils.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDOMWindowUtils.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsDOMWindowUtils.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsDOMWindowUtils.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -415,8 +415,6 @@ float aTopMargin, float aRightMargin, float aBottomMargin, - uint32_t aAlignmentX, - uint32_t aAlignmentY, nsIDOMElement* aElement, uint32_t aPriority) { @@ -451,7 +449,7 @@ aLeftMargin); nsLayoutUtils::SetDisplayPortMargins(content, presShell, displayportMargins, - aAlignmentX, aAlignmentY, aPriority); + aPriority); return NS_OK; } @@ -868,7 +866,7 @@ event.height = aHeight; event.tiltX = aTiltX; event.tiltY = aTiltY; - event.isPrimary = aIsPrimary; + event.isPrimary = (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == aInputSourceArg) ? true : aIsPrimary; event.clickCount = aClickCount; event.time = PR_IntervalNow(); event.mFlags.mIsSynthesizedForTests = aOptionalArgCount >= 10 ? aIsSynthesized : true; @@ -2068,7 +2066,7 @@ return NS_OK; } - *aFullZoom = presContext->DeviceContext()->GetPixelScale(); + *aFullZoom = presContext->DeviceContext()->GetFullZoom(); return NS_OK; } @@ -2130,7 +2128,15 @@ if (aType.EqualsLiteral("compositionstart")) { msg = NS_COMPOSITION_START; } else if (aType.EqualsLiteral("compositionend")) { - msg = NS_COMPOSITION_END; + // Now we don't support manually dispatching composition end with this + // API. A compositionend is dispatched when this is called with + // compositioncommitasis or compositioncommit automatically. For backward + // compatibility, this shouldn't return error in this case. + NS_WARNING("Don't call nsIDOMWindowUtils.sendCompositionEvent() for " + "compositionend. Instead, use it with compositioncommitasis or " + "compositioncommit. Then, compositionend will be automatically " + "dispatched."); + return NS_OK; } else if (aType.EqualsLiteral("compositionupdate")) { // Now we don't support manually dispatching composition update with this // API. A compositionupdate is dispatched when a DOM text event modifies @@ -2140,13 +2146,17 @@ "compositionupdate since it's ignored and the event is " "fired automatically when it's necessary"); return NS_OK; + } else if (aType.EqualsLiteral("compositioncommitasis")) { + msg = NS_COMPOSITION_COMMIT_AS_IS; + } else if (aType.EqualsLiteral("compositioncommit")) { + msg = NS_COMPOSITION_COMMIT; } else { return NS_ERROR_FAILURE; } WidgetCompositionEvent compositionEvent(true, msg, widget); InitEvent(compositionEvent); - if (msg != NS_COMPOSITION_START) { + if (msg != NS_COMPOSITION_START && msg != NS_COMPOSITION_COMMIT_AS_IS) { compositionEvent.mData = aData; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsFrameLoader.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsFrameLoader.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsFrameLoader.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsFrameLoader.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -432,6 +432,8 @@ } } + loadInfo->SetReferrerPolicy(mOwnerContent->OwnerDoc()->GetReferrerPolicy()); + // Default flags: int32_t flags = nsIWebNavigation::LOAD_FLAGS_NONE; @@ -2103,7 +2105,7 @@ nsCOMPtr containingApp = GetContainingApp(); ScrollingBehavior scrollingBehavior = DEFAULT_SCROLLING; - if (Preferences::GetBool("dom.browser_frames.useAsyncPanZoom", false) || + if (Preferences::GetBool("layers.async-pan-zoom.enabled", false) || mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozasyncpanzoom, nsGkAtoms::_true, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsFrameMessageManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsFrameMessageManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsFrameMessageManager.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsFrameMessageManager.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -976,6 +976,7 @@ nsIGlobalObject* nativeGlobal = xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject())); AutoEntryScript aes(nativeGlobal); + aes.TakeOwnershipOfErrorReporting(); JSContext* cx = aes.cx(); JS::Rooted object(cx, wrappedJS->GetJSObject()); @@ -1017,23 +1018,31 @@ aMessage.Length())); NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY); JS::Rooted syncv(cx, JS::BooleanValue(aIsSync)); - JS_DefineProperty(cx, param, "target", targetv, JSPROP_ENUMERATE); - JS_DefineProperty(cx, param, "name", jsMessage, JSPROP_ENUMERATE); - JS_DefineProperty(cx, param, "sync", syncv, JSPROP_ENUMERATE); - JS_DefineProperty(cx, param, "json", json, JSPROP_ENUMERATE); // deprecated - JS_DefineProperty(cx, param, "data", json, JSPROP_ENUMERATE); - JS_DefineProperty(cx, param, "objects", cpowsv, JSPROP_ENUMERATE); + bool ok = JS_DefineProperty(cx, param, "target", targetv, JSPROP_ENUMERATE) && + JS_DefineProperty(cx, param, "name", jsMessage, JSPROP_ENUMERATE) && + JS_DefineProperty(cx, param, "sync", syncv, JSPROP_ENUMERATE) && + JS_DefineProperty(cx, param, "json", json, JSPROP_ENUMERATE) && // deprecated + JS_DefineProperty(cx, param, "data", json, JSPROP_ENUMERATE) && + JS_DefineProperty(cx, param, "objects", cpowsv, JSPROP_ENUMERATE); + NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED); // message.principal == null if (!aPrincipal) { - JS_DefineProperty(cx, param, "principal", JS::UndefinedHandleValue, JSPROP_ENUMERATE); + bool ok = JS_DefineProperty(cx, param, "principal", + JS::UndefinedHandleValue, JSPROP_ENUMERATE); + NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED); } // message.principal = the principal else { JS::Rooted principalValue(cx); - rv = nsContentUtils::WrapNative(cx, aPrincipal, &NS_GET_IID(nsIPrincipal), &principalValue); - JS_DefineProperty(cx, param, "principal", principalValue, JSPROP_ENUMERATE); + nsresult rv = nsContentUtils::WrapNative(cx, aPrincipal, + &NS_GET_IID(nsIPrincipal), + &principalValue); + NS_ENSURE_SUCCESS(rv, rv); + bool ok = JS_DefineProperty(cx, param, "principal", principalValue, + JSPROP_ENUMERATE); + NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED); } JS::Rooted thisValue(cx, JS::UndefinedValue()); @@ -1057,8 +1066,9 @@ } else { // If the listener is a JS object which has receiveMessage function: if (!JS_GetProperty(cx, object, "receiveMessage", &funval) || - !funval.isObject()) + !funval.isObject()) { return NS_ERROR_UNEXPECTED; + } // Check if the object is even callable. NS_ENSURE_STATE(JS::IsCallable(&funval.toObject())); @@ -1076,15 +1086,14 @@ return NS_ERROR_UNEXPECTED; } - if (!JS_CallFunctionValue(cx, thisObject, funval, JS::HandleValueArray(argv), &rval)) { - nsJSUtils::ReportPendingException(cx); + if (!JS_CallFunctionValue(cx, thisObject, funval, + JS::HandleValueArray(argv), &rval)) { continue; } if (aJSONRetVal) { nsString json; if (!JS_Stringify(cx, &rval, JS::NullPtr(), JS::NullHandleValue, JSONCreator, &json)) { - nsJSUtils::ReportPendingException(cx); continue; } aJSONRetVal->AppendElement(json); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGkAtomList.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGkAtomList.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGkAtomList.h 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGkAtomList.h 2014-11-26 21:45:55.000000000 +0000 @@ -582,6 +582,7 @@ GK_ATOM(menuseparator, "menuseparator") GK_ATOM(message, "message") GK_ATOM(meta, "meta") +GK_ATOM(referrer, "referrer") GK_ATOM(meter, "meter") GK_ATOM(method, "method") GK_ATOM(microdataProperties, "microdataProperties") @@ -2324,3 +2325,5 @@ GK_ATOM(onmark, "onmark") GK_ATOM(onboundary, "onboundary") #endif + +GK_ATOM(vr_state, "vr-state") diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGlobalWindowCommands.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGlobalWindowCommands.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGlobalWindowCommands.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGlobalWindowCommands.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -83,6 +83,24 @@ const char * const sSelectTopString = "cmd_selectTop"; const char * const sSelectBottomString = "cmd_selectBottom"; +// Physical-direction movement and selection commands +const char * const sMoveLeftString = "cmd_moveLeft"; +const char * const sMoveRightString = "cmd_moveRight"; +const char * const sMoveUpString = "cmd_moveUp"; +const char * const sMoveDownString = "cmd_moveDown"; +const char * const sMoveLeft2String = "cmd_moveLeft2"; +const char * const sMoveRight2String = "cmd_moveRight2"; +const char * const sMoveUp2String = "cmd_moveUp2"; +const char * const sMoveDown2String = "cmd_moveDown2"; + +const char * const sSelectLeftString = "cmd_selectLeft"; +const char * const sSelectRightString = "cmd_selectRight"; +const char * const sSelectUpString = "cmd_selectUp"; +const char * const sSelectDownString = "cmd_selectDown"; +const char * const sSelectLeft2String = "cmd_selectLeft2"; +const char * const sSelectRight2String = "cmd_selectRight2"; +const char * const sSelectUp2String = "cmd_selectUp2"; +const char * const sSelectDown2String = "cmd_selectDown2"; #if 0 #pragma mark - @@ -116,6 +134,16 @@ // no member variables, please, we're stateless! }; +// this class implements physical-movement versions of the above +class nsPhysicalSelectMoveScrollCommand : public nsSelectionCommandsBase +{ +public: + + NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandContext); + + // no member variables, please, we're stateless! +}; + // this class implements other selection commands class nsSelectCommand : public nsSelectionCommandsBase { @@ -126,6 +154,16 @@ // no member variables, please, we're stateless! }; +// this class implements physical-movement versions of selection commands +class nsPhysicalSelectCommand : public nsSelectionCommandsBase +{ +public: + + NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandContext); + + // no member variables, please, we're stateless! +}; + #if 0 #pragma mark - #endif @@ -194,6 +232,39 @@ #pragma mark - #endif +// Helpers for nsSelectMoveScrollCommand and nsPhysicalSelectMoveScrollCommand +static void +AdjustFocusAfterCaretMove(nsPIDOMWindow* aWindow) +{ + // adjust the focus to the new caret position + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); + if (fm) { + nsCOMPtr result; + fm->MoveFocus(aWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET, + nsIFocusManager::FLAG_NOSCROLL, getter_AddRefs(result)); + } +} + +static bool +IsCaretOnInWindow(nsPIDOMWindow* aWindow, nsISelectionController* aSelCont) +{ + // We allow the caret to be moved with arrow keys on any window for which + // the caret is enabled. In particular, this includes caret-browsing mode + // in non-chrome documents. + bool caretOn = false; + aSelCont->GetCaretEnabled(&caretOn); + if (!caretOn) { + caretOn = Preferences::GetBool("accessibility.browsewithcaret"); + if (caretOn) { + nsCOMPtr docShell = aWindow->GetDocShell(); + if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) { + caretOn = false; + } + } + } + return caretOn; +} + static const struct BrowseCommand { const char *reverse, *forward; nsresult (NS_STDCALL nsISelectionController::*scroll)(bool); @@ -235,85 +306,158 @@ GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont)); NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED); - // We allow the caret to be moved with arrow keys on any window for which - // the caret is enabled. In particular, this includes caret-browsing mode - // in non-chrome documents. - bool caretOn = false; - selCont->GetCaretEnabled(&caretOn); - if (!caretOn) { - caretOn = Preferences::GetBool("accessibility.browsewithcaret"); - if (caretOn) { - nsCOMPtr docShell = piWindow->GetDocShell(); - if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) { - caretOn = false; - } - } - } + bool caretOn = IsCaretOnInWindow(piWindow, selCont); for (size_t i = 0; i < ArrayLength(browseCommands); i++) { bool forward = !strcmp(aCommandName, browseCommands[i].forward); if (forward || !strcmp(aCommandName, browseCommands[i].reverse)) { if (caretOn && browseCommands[i].move && NS_SUCCEEDED((selCont->*(browseCommands[i].move))(forward, false))) { - // adjust the focus to the new caret position - nsIFocusManager* fm = nsFocusManager::GetFocusManager(); - if (fm) { - nsCOMPtr result; - fm->MoveFocus(piWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET, - nsIFocusManager::FLAG_NOSCROLL, - getter_AddRefs(result)); - } + AdjustFocusAfterCaretMove(piWindow); return NS_OK; } return (selCont->*(browseCommands[i].scroll))(forward); } } + return NS_ERROR_NOT_IMPLEMENTED; } +// XXX It's not clear to me yet how we should handle the "scroll" option +// for these commands; for now, I'm mapping them back to ScrollCharacter, +// ScrollLine, etc., as if for horizontal-mode content, but this may need +// to be reconsidered once we have more experience with vertical content. +static const struct PhysicalBrowseCommand { + const char *command; + int16_t direction, amount; + nsresult (NS_STDCALL nsISelectionController::*scroll)(bool); +} physicalBrowseCommands[] = { + { sMoveLeftString, nsISelectionController::MOVE_LEFT, 0, + &nsISelectionController::ScrollCharacter }, + { sMoveRightString, nsISelectionController::MOVE_RIGHT, 0, + &nsISelectionController::ScrollCharacter }, + { sMoveUpString, nsISelectionController::MOVE_UP, 0, + &nsISelectionController::ScrollLine }, + { sMoveDownString, nsISelectionController::MOVE_DOWN, 0, + &nsISelectionController::ScrollLine }, + { sMoveLeft2String, nsISelectionController::MOVE_LEFT, 1, + &nsISelectionController::ScrollCharacter }, + { sMoveRight2String, nsISelectionController::MOVE_RIGHT, 1, + &nsISelectionController::ScrollCharacter }, + { sMoveUp2String, nsISelectionController::MOVE_UP, 1, + &nsISelectionController::CompleteScroll }, + { sMoveDown2String, nsISelectionController::MOVE_DOWN, 1, + &nsISelectionController::CompleteScroll }, +}; + +nsresult +nsPhysicalSelectMoveScrollCommand::DoCommand(const char *aCommandName, + nsISupports *aCommandContext) +{ + nsCOMPtr piWindow(do_QueryInterface(aCommandContext)); + nsCOMPtr selCont; + GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont)); + NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED); + + bool caretOn = IsCaretOnInWindow(piWindow, selCont); + + for (size_t i = 0; i < ArrayLength(physicalBrowseCommands); i++) { + const PhysicalBrowseCommand& cmd = physicalBrowseCommands[i]; + if (!strcmp(aCommandName, cmd.command)) { + int16_t dir = cmd.direction; + if (caretOn && + NS_SUCCEEDED(selCont->PhysicalMove(dir, cmd.amount, false))) { + AdjustFocusAfterCaretMove(piWindow); + return NS_OK; + } + + bool forward = (dir == nsISelectionController::MOVE_RIGHT || + dir == nsISelectionController::MOVE_DOWN); + return (selCont->*(cmd.scroll))(forward); + } + } + + return NS_ERROR_NOT_IMPLEMENTED; +} #if 0 #pragma mark - #endif +static const struct SelectCommand { + const char *reverse, *forward; + nsresult (NS_STDCALL nsISelectionController::*select)(bool, bool); +} selectCommands[] = { + { sSelectCharPreviousString, sSelectCharNextString, + &nsISelectionController::CharacterMove }, + { sSelectWordPreviousString, sSelectWordNextString, + &nsISelectionController::WordMove }, + { sSelectBeginLineString, sSelectEndLineString, + &nsISelectionController::IntraLineMove }, + { sSelectLinePreviousString, sSelectLineNextString, + &nsISelectionController::LineMove }, + { sSelectPageUpString, sSelectPageDownString, + &nsISelectionController::PageMove }, + { sSelectTopString, sSelectBottomString, + &nsISelectionController::CompleteMove } +}; + nsresult -nsSelectCommand::DoCommand(const char *aCommandName, nsISupports *aCommandContext) +nsSelectCommand::DoCommand(const char *aCommandName, + nsISupports *aCommandContext) { nsCOMPtr piWindow(do_QueryInterface(aCommandContext)); nsCOMPtr selCont; GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont)); NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED); - nsresult rv = NS_ERROR_NOT_IMPLEMENTED; - // These commands are so the browser can use caret navigation key bindings - // Helps with accessibility - aaronl@netscape.com - if (!nsCRT::strcmp(aCommandName, sSelectCharPreviousString)) - rv = selCont->CharacterMove(false, true); - else if (!nsCRT::strcmp(aCommandName, sSelectCharNextString)) - rv = selCont->CharacterMove(true, true); - else if (!nsCRT::strcmp(aCommandName, sSelectWordPreviousString)) - rv = selCont->WordMove(false, true); - else if (!nsCRT::strcmp(aCommandName, sSelectWordNextString)) - rv = selCont->WordMove(true, true); - else if (!nsCRT::strcmp(aCommandName, sSelectBeginLineString)) - rv = selCont->IntraLineMove(false, true); - else if (!nsCRT::strcmp(aCommandName, sSelectEndLineString)) - rv = selCont->IntraLineMove(true, true); - else if (!nsCRT::strcmp(aCommandName, sSelectLinePreviousString)) - rv = selCont->LineMove(false, true); - else if (!nsCRT::strcmp(aCommandName, sSelectLineNextString)) - rv = selCont->LineMove(true, true); - else if (!nsCRT::strcmp(aCommandName, sSelectPageUpString)) - rv = selCont->PageMove(false, true); - else if (!nsCRT::strcmp(aCommandName, sSelectPageDownString)) - rv = selCont->PageMove(true, true); - else if (!nsCRT::strcmp(aCommandName, sSelectTopString)) - rv = selCont->CompleteMove(false, true); - else if (!nsCRT::strcmp(aCommandName, sSelectBottomString)) - rv = selCont->CompleteMove(true, true); + for (size_t i = 0; i < ArrayLength(selectCommands); i++) { + bool forward = !strcmp(aCommandName, selectCommands[i].forward); + if (forward || !strcmp(aCommandName, selectCommands[i].reverse)) { + return (selCont->*(selectCommands[i].select))(forward, true); + } + } + return NS_ERROR_NOT_IMPLEMENTED; +} + +#if 0 +#pragma mark - +#endif + +static const struct PhysicalSelectCommand { + const char *command; + int16_t direction, amount; +} physicalSelectCommands[] = { + { sSelectLeftString, nsISelectionController::MOVE_LEFT, 0 }, + { sSelectRightString, nsISelectionController::MOVE_RIGHT, 0 }, + { sSelectUpString, nsISelectionController::MOVE_UP, 0 }, + { sSelectDownString, nsISelectionController::MOVE_DOWN, 0 }, + { sSelectLeft2String, nsISelectionController::MOVE_LEFT, 1 }, + { sSelectRight2String, nsISelectionController::MOVE_RIGHT, 1 }, + { sSelectUp2String, nsISelectionController::MOVE_UP, 1 }, + { sSelectDown2String, nsISelectionController::MOVE_DOWN, 1 } +}; + +nsresult +nsPhysicalSelectCommand::DoCommand(const char *aCommandName, + nsISupports *aCommandContext) +{ + nsCOMPtr piWindow(do_QueryInterface(aCommandContext)); + nsCOMPtr selCont; + GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont)); + NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED); - return rv; + for (size_t i = 0; i < ArrayLength(physicalSelectCommands); i++) { + if (!strcmp(aCommandName, physicalSelectCommands[i].command)) { + return selCont->PhysicalMove(physicalSelectCommands[i].direction, + physicalSelectCommands[i].amount, + true); + } + } + + return NS_ERROR_NOT_IMPLEMENTED; } #if 0 @@ -868,6 +1012,15 @@ NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sCharPreviousString); NS_REGISTER_LAST_COMMAND(nsSelectMoveScrollCommand, sCharNextString); + NS_REGISTER_FIRST_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveLeftString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveRightString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveUpString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveDownString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveLeft2String); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveRight2String); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveUp2String); + NS_REGISTER_LAST_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveDown2String); + NS_REGISTER_FIRST_COMMAND(nsSelectCommand, sSelectCharPreviousString); NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectCharNextString); NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectWordPreviousString); @@ -881,6 +1034,15 @@ NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectTopString); NS_REGISTER_LAST_COMMAND(nsSelectCommand, sSelectBottomString); + NS_REGISTER_FIRST_COMMAND(nsPhysicalSelectCommand, sSelectLeftString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectRightString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectUpString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectDownString); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectLeft2String); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectRight2String); + NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectUp2String); + NS_REGISTER_LAST_COMMAND(nsPhysicalSelectCommand, sSelectDown2String); + NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_cut"); NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_copy"); NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_paste"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGlobalWindow.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGlobalWindow.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGlobalWindow.cpp 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGlobalWindow.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -190,10 +190,13 @@ #include "mozilla/dom/GamepadService.h" #endif +#include "mozilla/dom/VRDevice.h" + #include "nsRefreshDriver.h" #include "mozilla/dom/SelectionChangeEvent.h" +#include "mozilla/AddonPathService.h" #include "mozilla/Services.h" #include "mozilla/Telemetry.h" #include "nsLocation.h" @@ -620,8 +623,6 @@ virtual bool delete_(JSContext *cx, JS::Handle proxy, JS::Handle id, bool *bp) const MOZ_OVERRIDE; - virtual bool enumerate(JSContext *cx, JS::Handle proxy, - JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, JS::Handle proxy, bool *succeeded) const MOZ_OVERRIDE; @@ -649,9 +650,11 @@ JS::Handle id, bool *bp) const MOZ_OVERRIDE; virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle proxy, JS::AutoIdVector &props) const MOZ_OVERRIDE; + virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle proxy, + JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, JS::Handle proxy, unsigned flags, - JS::MutableHandle vp) const MOZ_OVERRIDE; + JS::MutableHandle objp) const MOZ_OVERRIDE; virtual const char *className(JSContext *cx, JS::Handle wrapper) const MOZ_OVERRIDE; @@ -830,22 +833,6 @@ } bool -nsOuterWindowProxy::enumerate(JSContext *cx, JS::Handle proxy, - JS::AutoIdVector &props) const -{ - // Just our indexed stuff followed by our "normal" own property names. - if (!AppendIndexedPropertyNames(cx, proxy, props)) { - return false; - } - - JS::AutoIdVector innerProps(cx); - if (!js::Wrapper::enumerate(cx, proxy, innerProps)) { - return false; - } - return js::AppendUnique(cx, props, innerProps); -} - -bool nsOuterWindowProxy::preventExtensions(JSContext *cx, JS::Handle proxy, bool *succeeded) const @@ -943,12 +930,28 @@ } bool +nsOuterWindowProxy::getEnumerablePropertyKeys(JSContext *cx, JS::Handle proxy, + JS::AutoIdVector &props) const +{ + // Just our indexed stuff followed by our "normal" own property names. + if (!AppendIndexedPropertyNames(cx, proxy, props)) { + return false; + } + + JS::AutoIdVector innerProps(cx); + if (!js::Wrapper::getEnumerablePropertyKeys(cx, proxy, innerProps)) { + return false; + } + return js::AppendUnique(cx, props, innerProps); +} + +bool nsOuterWindowProxy::iterate(JSContext *cx, JS::Handle proxy, - unsigned flags, JS::MutableHandle vp) const + unsigned flags, JS::MutableHandle objp) const { // BaseProxyHandler::iterate seems to do what we want here: fall // back on the property names returned from keys() and enumerate(). - return js::BaseProxyHandler::iterate(cx, proxy, flags, vp); + return js::BaseProxyHandler::iterate(cx, proxy, flags, objp); } bool @@ -1133,7 +1136,8 @@ mCleanedUp(false), mDialogAbuseCount(0), mAreDialogsEnabled(true), - mCanSkipCCGeneration(0) + mCanSkipCCGeneration(0), + mVRDevicesInitialized(false) { nsLayoutStatics::AddRef(); @@ -1770,6 +1774,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads) #endif + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDevices) + // Traverse stuff from nsPIDOMWindow NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget) @@ -1831,6 +1837,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads) #endif + NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDevices) + // Unlink stuff from nsPIDOMWindow NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler) NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget) @@ -2269,6 +2277,14 @@ top = aNewInner->GetTop(); } JS::CompartmentOptions options; + + // Sometimes add-ons load their own XUL windows, either as separate top-level + // windows or inside a browser element. In such cases we want to tag the + // window's compartment with the add-on ID. See bug 1092156. + if (nsContentUtils::IsSystemPrincipal(aPrincipal)) { + options.setAddonId(MapURIToAddonID(aURI)); + } + if (top) { if (top->GetGlobalJSObject()) { options.setSameZoneAs(top->GetGlobalJSObject()); @@ -2412,9 +2428,10 @@ bool thisChrome = IsChromeWindow(); - // Check if we're near the stack limit before we get anywhere near the - // transplanting code. We use a conservative check since we'll use a little - // more space before we actually hit the critical "can't fail" path. + // Check if we're anywhere near the stack limit before we reach the + // transplanting code, since it has no good way to handle errors. This uses + // the untrusted script limit, which is not strictly necessary since no + // actual script should run. JS_CHECK_RECURSION_CONSERVATIVE(cx, return NS_ERROR_FAILURE); nsCOMPtr wsh = do_QueryInterface(aState); @@ -5346,26 +5363,11 @@ FORWARD_TO_OUTER_OR_THROW(MatchMedia, (aMediaQueryList, aError), aError, nullptr); - // We need this now to ensure that we have a non-null |presContext| - // when we ought to. - // This is similar to EnsureSizeUpToDate, but only flushes frames. - nsGlobalWindow *parent = static_cast(GetPrivateParent()); - if (parent) { - parent->FlushPendingNotifications(Flush_Frames); - } - - if (!mDocShell) { - return nullptr; - } - - nsRefPtr presContext; - mDocShell->GetPresContext(getter_AddRefs(presContext)); - - if (!presContext) { + if (!mDoc) { return nullptr; } - return presContext->MatchMedia(aMediaQueryList); + return mDoc->MatchMedia(aMediaQueryList); } NS_IMETHODIMP @@ -5928,7 +5930,7 @@ } nsresult -nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust) +nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust, gfx::VRHMDInfo* aHMD) { MOZ_ASSERT(IsOuterWindow()); @@ -5950,7 +5952,7 @@ if (!window) return NS_ERROR_FAILURE; if (rootItem != mDocShell) - return window->SetFullScreenInternal(aFullScreen, aRequireTrust); + return window->SetFullScreenInternal(aFullScreen, aRequireTrust, aHMD); // make sure we don't try to set full screen on a non-chrome window, // which might happen in embedding world @@ -5985,8 +5987,13 @@ // want the content to fill the entire client area of the emulator window. if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) { nsCOMPtr widget = GetMainWidget(); - if (widget) - widget->MakeFullScreen(aFullScreen); + if (widget) { + nsCOMPtr screen; + if (aHMD) { + screen = aHMD->GetScreen(); + } + widget->MakeFullScreen(aFullScreen, screen); + } } if (!mFullScreen) { @@ -6375,7 +6382,7 @@ } already_AddRefed -nsGlobalWindow::Fetch(const RequestOrScalarValueString& aInput, +nsGlobalWindow::Fetch(const RequestOrUSVString& aInput, const RequestInit& aInit, ErrorResult& aRv) { return FetchRequest(this, aInput, aInit, aRv); @@ -7783,46 +7790,15 @@ return rv.ErrorCode(); } -JSObject* nsGlobalWindow::CallerGlobal() -{ - JSContext *cx = nsContentUtils::GetCurrentJSContext(); - if (!cx) { - NS_ERROR("Please don't call this method from C++!"); - - return nullptr; - } - - // If somebody does sameOriginIframeWindow.postMessage(...), they probably - // expect the .source attribute of the resulting message event to be |window| - // rather than |sameOriginIframeWindow|, even though the transparent wrapper - // semantics of same-origin access will cause us to be in the iframe's - // compartment at the time of the call. This means that we want the incumbent - // global here, rather than the global of the current compartment. - // - // There are various edge cases in which the incumbent global and the current - // global would not be same-origin. They include: - // * A privileged caller (System Principal or Expanded Principal) manipulating - // less-privileged content via Xray Waivers. - // * An unprivileged caller invoking a cross-origin function that was exposed - // to it by privileged code (i.e. Sandbox.importFunction). - // - // In these cases, we probably don't want the privileged global appearing in the - // .source attribute. So we fall back to the compartment global there. - JS::Rooted incumbentGlobal(cx, &IncumbentJSGlobal()); - JS::Rooted compartmentGlobal(cx, JS::CurrentGlobalOrNull(cx)); - nsIPrincipal* incumbentPrin = nsContentUtils::ObjectPrincipal(incumbentGlobal); - nsIPrincipal* compartmentPrin = nsContentUtils::ObjectPrincipal(compartmentGlobal); - return incumbentPrin->EqualsConsideringDomain(compartmentPrin) ? incumbentGlobal - : compartmentGlobal; -} - - nsGlobalWindow* nsGlobalWindow::CallerInnerWindow() { JSContext *cx = nsContentUtils::GetCurrentJSContext(); NS_ENSURE_TRUE(cx, nullptr); - JS::Rooted scope(cx, CallerGlobal()); + nsIGlobalObject* global = GetIncumbentGlobal(); + NS_ENSURE_TRUE(global, nullptr); + JS::Rooted scope(cx, global->GetGlobalJSObject()); + NS_ENSURE_TRUE(scope, nullptr); // When Jetpack runs content scripts inside a sandbox, it uses // sandboxPrototype to make them appear as though they're running in the @@ -7830,7 +7806,7 @@ // the |source| of the received message to be the window set as the // sandboxPrototype. This used to work incidentally for unrelated reasons, but // now we need to do some special handling to support it. - { + if (xpc::IsSandbox(scope)) { JSAutoCompartment ac(cx, scope); JS::Rooted scopeProto(cx); bool ok = JS_GetPrototype(cx, scope, &scopeProto); @@ -7838,26 +7814,14 @@ if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) && (scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtOuter = */ false))) { - scope = scopeProto; + global = xpc::NativeGlobal(scopeProto); + NS_ENSURE_TRUE(global, nullptr); } } - JSAutoCompartment ac(cx, scope); - // We don't use xpc::WindowOrNull here because we want to be able to tell - // apart the cases of "scope is not an nsISupports at all" and "scope is an - // nsISupports that's not a window". It's not clear whether that's desirable, - // see bug 984467. - nsISupports* native = - nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, scope); - if (!native) - return nullptr; - - // The calling window must be holding a reference, so we can just return a - // raw pointer here and let the QI's addref be balanced by the nsCOMPtr - // destructor's release. - nsCOMPtr win = do_QueryInterface(native); - if (!win) - return GetCurrentInnerWindowInternal(); + // The calling window must be holding a reference, so we can return a weak + // pointer. + nsCOMPtr win = do_QueryInterface(global); return static_cast(win.get()); } @@ -8258,10 +8222,9 @@ else { // In case the global is not a window, it can be a sandbox, and the sandbox's // principal can be used for the security check. - JSObject *global = CallerGlobal(); + nsIGlobalObject* global = GetIncumbentGlobal(); NS_ASSERTION(global, "Why is there no global object?"); - JSCompartment *compartment = js::GetObjectCompartment(global); - callerPrin = xpc::GetCompartmentPrincipal(compartment); + callerPrin = global->PrincipalOrNull(); } if (!callerPrin) { return; @@ -12023,6 +11986,9 @@ // inner window that's calling window.setTimeout(). forwardTo = CallerInnerWindow(); + if (!forwardTo && nsContentUtils::IsCallerChrome()) { + forwardTo = currentInner; + } if (!forwardTo) { aError.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; @@ -12241,14 +12207,15 @@ if (IsOuterWindow()) { nsGlobalWindow* callerInner = CallerInnerWindow(); - NS_ENSURE_TRUE(callerInner, NS_ERROR_NOT_AVAILABLE); + NS_ENSURE_TRUE(callerInner || nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); // If the caller and the callee share the same outer window, // forward to the callee inner. Else, we forward to the current // inner (e.g. someone is calling setTimeout() on a reference to // some other window). - if (callerInner->GetOuterWindow() == this && + if (callerInner && + callerInner->GetOuterWindow() == this && callerInner->IsInnerWindow()) { return callerInner->SetTimeoutOrInterval(aIsInterval, aReturn); } @@ -13461,7 +13428,26 @@ mGamepads.EnumerateRead(EnumGamepadsForSync, nullptr); } } -#endif +#endif // MOZ_GAMEPAD + +bool +nsGlobalWindow::GetVRDevices(nsTArray>& aDevices) +{ + FORWARD_TO_INNER(GetVRDevices, (aDevices), false); + + if (!mVRDevicesInitialized) { + bool ok = mozilla::dom::VRDevice::CreateAllKnownVRDevices(ToSupports(this), mVRDevices); + if (!ok) { + mVRDevices.Clear(); + return false; + } + } + + mVRDevicesInitialized = true; + aDevices = mVRDevices; + return true; +} + // nsGlobalChromeWindow implementation NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow) @@ -14132,8 +14118,12 @@ nsGlobalWindow::ClearDocumentDependentSlots(JSContext* aCx) { MOZ_ASSERT(IsInnerWindow()); - WindowBinding::ClearCachedDocumentValue(aCx, this); - WindowBinding::ClearCachedPerformanceValue(aCx, this); + + // If JSAPI OOMs here, there is basically nothing we can do to recover safely. + if (!WindowBinding::ClearCachedDocumentValue(aCx, this) || + !WindowBinding::ClearCachedPerformanceValue(aCx, this)) { + MOZ_CRASH("Unhandlable OOM while clearing document dependent slots."); + } } /* static */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGlobalWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGlobalWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsGlobalWindow.h 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsGlobalWindow.h 2014-11-26 21:45:55.000000000 +0000 @@ -104,13 +104,14 @@ class External; class Function; class Gamepad; +class VRDevice; class MediaQueryList; class MozSelfSupport; class Navigator; class OwningExternalOrWindowProxy; class Promise; struct RequestInit; -class RequestOrScalarValueString; +class RequestOrUSVString; class Selection; class SpeechSynthesis; class WakeLock; @@ -118,6 +119,9 @@ class IDBFactory; } // namespace indexedDB } // namespace dom +namespace gfx { +class VRHMDInfo; +} // namespace gfx } // namespace mozilla extern nsresult @@ -464,7 +468,8 @@ virtual void RefreshCompartmentPrincipal(); // Outer windows only. - virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust); + virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust, + mozilla::gfx::VRHMDInfo *aHMD = nullptr); bool FullScreen() const; // Inner windows only. @@ -734,6 +739,8 @@ void EnableGamepadUpdates(); void DisableGamepadUpdates(); + // Get the VR devices for this window, initializing if necessary + bool GetVRDevices(nsTArray>& aDevices); #define EVENT(name_, id_, type_, struct_) \ mozilla::dom::EventHandlerNonNull* GetOn##name_() \ @@ -857,7 +864,7 @@ void Alert(mozilla::ErrorResult& aError); void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError); bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError); - already_AddRefed Fetch(const mozilla::dom::RequestOrScalarValueString& aInput, + already_AddRefed Fetch(const mozilla::dom::RequestOrUSVString& aInput, const mozilla::dom::RequestInit& aInit, mozilla::ErrorResult& aRv); void Prompt(const nsAString& aMessage, const nsAString& aInitial, @@ -1092,7 +1099,6 @@ } void FreeInnerObjects(); - JSObject *CallerGlobal(); nsGlobalWindow *CallerInnerWindow(); // Only to be called on an inner window. @@ -1631,6 +1637,13 @@ // This is the CC generation the last time we called CanSkip. uint32_t mCanSkipCCGeneration; + // Did VR get initialized for this window? + bool mVRDevicesInitialized; + // The VRDevies for this window + nsTArray> mVRDevices; + // Any attached HMD when fullscreen + nsRefPtr mVRHMDInfo; + friend class nsDOMScriptableHelper; friend class nsDOMWindowUtils; friend class PostMessageEvent; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsIDocument.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsIDocument.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/nsIDocument.h 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/nsIDocument.h 2014-11-26 21:45:55.000000000 +0000 @@ -19,12 +19,15 @@ #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member #include "nsTHashtable.h" // for member +#include "mozilla/net/ReferrerPolicy.h" // for member #include "nsWeakReference.h" #include "mozilla/dom/DocumentBinding.h" #include "mozilla/WeakPtr.h" #include "Units.h" #include "nsExpirationTracker.h" #include "nsClassHashtable.h" +#include "prclist.h" +#include "gfxVR.h" class imgIRequest; class nsAString; @@ -113,6 +116,7 @@ class HTMLBodyElement; struct LifecycleCallbackArgs; class Link; +class MediaQueryList; class GlobalObject; class NodeFilter; class NodeIterator; @@ -132,12 +136,18 @@ template class CallbackObjectHolder; typedef CallbackObjectHolder NodeFilterHolder; + +struct FullScreenOptions { + FullScreenOptions() { } + nsRefPtr mVRHMDDevice; +}; + } // namespace dom } // namespace mozilla #define NS_IDOCUMENT_IID \ -{ 0x1f343423, 0x957c, 0x4da3, \ - { 0xaa, 0xa3, 0x07, 0x37, 0x54, 0x3e, 0x79, 0x2a } } +{ 0xf63d2f6e, 0xd1c1, 0x49b9, \ + { 0x88, 0x26, 0xd5, 0x9e, 0x5d, 0x72, 0x2a, 0x42 } } // Enum for requesting a particular type of document when creating a doc enum DocumentFlavor { @@ -161,6 +171,7 @@ NS_GetContentList(nsINode* aRootNode, int32_t aMatchNameSpaceId, const nsAString& aTagname); + //---------------------------------------------------------------------- // Document interface. This is implemented by all document objects in @@ -169,6 +180,7 @@ { typedef mozilla::dom::GlobalObject GlobalObject; public: + typedef mozilla::net::ReferrerPolicy ReferrerPolicy; typedef mozilla::dom::Element Element; NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID) @@ -272,6 +284,15 @@ virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) = 0; /** + * Return the referrer policy of the document. Return "default" if there's no + * valid meta referrer tag found in the document. + */ + ReferrerPolicy GetReferrerPolicy() const + { + return mReferrerPolicy; + } + + /** * Set the principal responsible for this document. */ virtual void SetPrincipal(nsIPrincipal *aPrincipal) = 0; @@ -1051,7 +1072,8 @@ * the \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + '; +} + +function createIframedFormTest(schemeFrom, schemeTo, policy) { + var actionUrl = schemeTo + '://' + BASE_URL; + + return '\n\ + \n\ + \n\ + \n\ + \n\ + \n\ +
\n\ + \n\ + \n\ + \n\ + \n\ +
\n\ + \n\ + \n\ + '; +} + +function createIframedWindowLocationTest(schemeFrom, schemeTo, policy) { + var url = createTestUrl( + schemeFrom, schemeTo, policy, 'test', 'window.location'); + + return '\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + '; +} + +function createPolicyTest(refpol) { + return '\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + '; +} + +function handleRequest(request, response) { + var sharedKey = 'bug704320.sjs'; + var params = request.queryString.split('&'); + var action = params[0].split('=')[1]; + + if (action === 'create-1st-level-iframe') { + // ?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin + var schemeFrom = params[1].split('=')[1]; + var schemeTo = params[2].split('=')[1]; + var policy = params[3].split('=')[1]; + + response.setHeader('Content-Type', 'text/html; charset=utf-8', false); + response.setHeader('Cache-Control', 'no-cache', false); + response.write(createTest(schemeFrom, schemeTo, policy)); + } + else if (action === 'create-2nd-level-iframe') { + // ?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=origin&type=form" + var schemeFrom = params[1].split('=')[1]; + var schemeTo = params[2].split('=')[1]; + var policy = params[3].split('=')[1]; + var type = params[4].split('=')[1]; + + response.setHeader('Content-Type', 'text/html; charset=utf-8', false); + response.setHeader('Cache-Control', 'no-cache', false); + + if (type === 'form') { + response.write(createIframedFormTest(schemeFrom, schemeTo, policy)); + } else if (type === 'window.location') { + response.write(createIframedWindowLocationTest( + schemeFrom, schemeTo, policy)); + } + } + else if (action === 'test') { + // ?action=test&scheme=http-to-https&policy=origin&type=img + var scheme = params[1].split('=')[1]; + var policy = params[2].split('=')[1]; + var type = params[3].split('=')[1]; + var result = getSharedState(sharedKey); + + if (result === '') { + result = {}; + } else { + result = JSON.parse(result); + } + + if (!result[type]) { + result[type] = {}; + } + + if (!result[type][scheme]) { + result[type][scheme] = {}; + } + + if (request.hasHeader('Referer')) { + result[type][scheme][policy] = request.getHeader('Referer'); + } else { + result[type][scheme][policy] = ''; + } + + setSharedState(sharedKey, JSON.stringify(result)); + + if (type === 'link') { + var loc = 'https://example.com/tests/dom/base/test/file_bug704320_redirect.html'; + response.setStatusLine('1.1', 302, 'Found'); + response.setHeader('Location', loc, false); + } + + if (type === 'window.open') { + response.setHeader('Cache-Control', 'no-cache', false); + response.setHeader('Content-Type', 'text/html', false); + response.write(''); + } + } + else if (action === 'get-test-results') { + // ?action=get-result + response.setHeader('Cache-Control', 'no-cache', false); + response.setHeader('Content-Type', 'text/plain', false); + response.write(getSharedState(sharedKey)); + } + else if (action === 'generate-policy-test') { + // ?action=generate-policy-test&policy=b64-encoded-string + response.setHeader('Cache-Control', 'no-cache', false); + response.setHeader('Content-Type', 'text/html', false); + var refpol = unescape(params[1].split('=')[1]); + response.write(createPolicyTest(refpol)); + } +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/chrome.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/chrome.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/chrome.ini 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/chrome.ini 2014-11-26 21:45:55.000000000 +0000 @@ -33,6 +33,7 @@ [test_bug549682.xul] [test_bug571390.xul] [test_bug574596.html] +[test_bug1098074_throw_from_ReceiveMessage.xul] skip-if = buildapp == 'mulet' [test_bug599295.html] [test_bug616841.xul] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/cpows_child.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/cpows_child.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/cpows_child.js 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/cpows_child.js 2014-11-26 21:45:55.000000000 +0000 @@ -17,6 +17,7 @@ } compartment_test(); regexp_test(); + postmessage_test(); sync_test(); async_test(); rpc_test(); @@ -179,6 +180,11 @@ sendSyncMessage("cpows:regexp_test", {}, { regexp: /myRegExp/g }); } +function postmessage_test() +{ + sendSyncMessage("cpows:postmessage_test", {}, { win: content.window }); +} + function sync_test() { dump('beginning cpow sync test\n'); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/cpows_parent.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/cpows_parent.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/cpows_parent.xul 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/cpows_parent.xul 2014-11-26 21:45:55.000000000 +0000 @@ -66,6 +66,7 @@ ok(obj.a === 3, "constructor call"); ok(document.title === "Hello, Kitty", "document node"); is(typeof document.cookie, "string", "can get document.cookie"); + is(typeof document.defaultView.navigator.userAgent, "string", "can get navigator.userAgent"); data.i = 6; data.b = false; @@ -269,6 +270,12 @@ is(regexp.toString(), shell.toString(), ".compile works right"); } + function recvPostMessageTest(message) { + let win = message.objects.win; + win.postMessage('nookery', '*'); + ok(true, "Didn't crash invoking postMessage over CPOW"); + } + let savedWilldieObj; let wontDie = {f:2, __exposedProps__: {"f": "r"}}; function recvLifetimeTest1(message) { @@ -326,6 +333,7 @@ } mm.addMessageListener("cpows:compartment_test", recvCompartmentTest); mm.addMessageListener("cpows:regexp_test", recvRegExpTest); + mm.addMessageListener("cpows:postmessage_test", recvPostMessageTest); mm.addMessageListener("cpows:lifetime_test_1", recvLifetimeTest1); mm.addMessageListener("cpows:lifetime_test_2", recvLifetimeTest2); mm.loadFrameScript("chrome://mochitests/content/chrome/dom/base/test/chrome/cpows_child.js", true); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,50 @@ + + + + + + + + + + Mozilla Bug 1098074 + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/csp/file_form-action.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/csp/file_form-action.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/csp/file_form-action.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/csp/file_form-action.html 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,15 @@ + + + + Bug 529697 - Test mapping of form submission to form-action + + +
+ +
+ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/csp/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/csp/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/csp/mochitest.ini 2014-11-14 09:37:20.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/csp/mochitest.ini 2014-11-26 21:45:55.000000000 +0000 @@ -100,6 +100,7 @@ file_multi_policy_injection_bypass.html^headers^ file_multi_policy_injection_bypass_2.html file_multi_policy_injection_bypass_2.html^headers^ + file_form-action.html [test_base-uri.html] [test_connect-src.html] @@ -124,6 +125,8 @@ [test_policyuri_regression_from_multipolicy.html] [test_nonce_source.html] [test_CSP_bug941404.html] +[test_form-action.html] +skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observers are not available in child processes [test_hash_source.html] skip-if = e10s || buildapp == 'b2g' # can't compute hashes in child process (bug 958702) [test_self_none_as_hostname_confusion.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/csp/test_form-action.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/csp/test_form-action.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/csp/test_form-action.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/csp/test_form-action.html 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,105 @@ + + + + Bug 529697 - Test mapping of form submission to form-action + + + + + +

+ + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_preload_common.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_preload_common.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_preload_common.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_preload_common.js 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,34 @@ +// Common code for the iframes used by bug704320_preload. + +var loadCount = 0; + +// Called by the various onload handlers to indicate that a resource has +// been fully loaded. We require three loads to complete (img, script, +// link) for this test. +function incrementLoad(tag) { + loadCount++; + if (loadCount == 3) { + window.parent.postMessage("childLoadComplete", window.location.origin); + } else if (loadCount > 3) { + document.write("

Too Many Load Events!

"); + window.parent.postMessage("childOverload", window.location.origin); + } +} + +// This is same as incrementLoad, but the caller passes in the loadCount. +function incrementLoad2(tag, expectedLoadCount) { + loadCount++; + if (loadCount == expectedLoadCount) { + window.parent.postMessage("childLoadComplete", window.location.origin); + } else if (loadCount > expectedLoadCount) { + document.write("

Too Many Load Events!

"); + window.parent.postMessage("childOverload", window.location.origin); + } +} + +// in case something fails to load, cause the test to fail. +function postfail(msg) { + window.parent.postMessage("fail-" + msg, window.location.origin); +} + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_preload_noreuse.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_preload_noreuse.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_preload_noreuse.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_preload_noreuse.html 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_preload_reuse.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_preload_reuse.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_preload_reuse.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_preload_reuse.html 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_redirect.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_redirect.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/file_bug704320_redirect.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/file_bug704320_redirect.html 2014-11-26 21:45:55.000000000 +0000 @@ -0,0 +1,10 @@ + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/mochitest.ini 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/mochitest.ini 2014-11-26 21:45:55.000000000 +0000 @@ -52,6 +52,8 @@ bug696301-script-1.js bug696301-script-1.js^headers^ bug696301-script-2.js + bug704320.sjs + bug704320_counter.sjs bug819051.sjs copypaste.js delayedServerEvents.sjs @@ -138,6 +140,10 @@ file_bug687859-http.js^headers^ file_bug687859-inherit.js file_bug692434.xml + file_bug704320_preload_common.js + file_bug704320_preload_reuse.html + file_bug704320_preload_noreuse.html + file_bug704320_redirect.html file_bug707142_baseline.json file_bug707142_bom.json file_bug707142_utf-16.json @@ -593,6 +599,10 @@ [test_bug698381.html] [test_bug698384.html] [test_bug704063.html] +[test_bug704320.html] +skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g (Needs multiple window.open support) android(times out, bug 1100609) e10s(randomly fails, bug 1100362) +[test_bug704320_policyset.html] +[test_bug704320_preload.html] [test_bug707142.html] [test_bug708620.html] [test_bug711047.html] @@ -674,12 +684,19 @@ [test_ipc_messagemanager_blob.html] skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226 [test_meta_viewport0.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_meta_viewport1.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_meta_viewport2.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_meta_viewport3.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_meta_viewport4.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_meta_viewport5.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_meta_viewport6.html] +skip-if = buildapp != 'b2g' # meta-viewport tag support is only on b2g [test_mozfiledataurl.html] skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT [test_mozMatchesSelector.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug338583.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug338583.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug338583.html 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug338583.html 2014-11-26 21:45:55.000000000 +0000 @@ -353,13 +353,13 @@ function fnMessageListenerTest3h(e) { fnMessageListenerTest3h.msg_ok = (fnMessageListenerTest3h.msg_ok && e.data == "ok"); - fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.msg_ok && e.lastEventId == ""); + fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.id_ok && e.lastEventId == ""); } function doTest3_h(test_id) { gEventSourceObj3_h = new EventSource("badMessageEvent2.eventsource"); - gEventSourceObj3_h.addEventListener('message event', fnMessageListenerTest3h, true); + gEventSourceObj3_h.addEventListener('message', fnMessageListenerTest3h, true); fnMessageListenerTest3h.msg_ok = true; fnMessageListenerTest3h.id_ok = true; @@ -375,7 +375,7 @@ } gEventSourceObj3_h.close(); setTestHasFinished(test_id); - }, parseInt(3000*stress_factor)); + }, parseInt(6000*stress_factor)); } // in order to test (4) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug704320.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug704320.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug704320.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug704320.html 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,232 @@ + + + + + + Test for Bug 704320 + + + + +Mozilla Bug 704320 +

+
+
+
+
+ + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug704320_policyset.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug704320_policyset.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug704320_policyset.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug704320_policyset.html 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,179 @@ + + + + + + + Test policies for Bug 704320 + + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug704320_preload.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug704320_preload.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_bug704320_preload.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_bug704320_preload.html 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,189 @@ + + + + + + + Test preloads for Bug 704320 + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_url.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_url.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/test/test_url.html 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/test/test_url.html 2014-11-26 21:45:56.000000000 +0000 @@ -327,5 +327,14 @@ var u = new URL(url); ok(u.origin, 'http://mochi.test:8888', "The URL generated from a blob URI has an origin"); + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/URL.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/URL.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/URL.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/URL.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -239,17 +239,6 @@ void URL::GetOrigin(nsString& aOrigin, ErrorResult& aRv) const { - nsCOMPtr uriWithPrincipal = do_QueryInterface(mURI); - if (uriWithPrincipal) { - nsCOMPtr principal; - uriWithPrincipal->GetPrincipal(getter_AddRefs(principal)); - - if (principal) { - nsContentUtils::GetUTFOrigin(principal, aOrigin); - return; - } - } - nsContentUtils::GetUTFOrigin(mURI, aOrigin); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/WebSocket.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/WebSocket.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/base/WebSocket.cpp 2014-11-14 09:37:19.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/base/WebSocket.cpp 2014-11-26 21:45:55.000000000 +0000 @@ -1470,7 +1470,9 @@ mOriginDocument = nullptr; nsCOMPtr loadInfo = - new LoadInfo(mPrincipal, + new LoadInfo(doc ? + doc->NodePrincipal() : mPrincipal.get(), + mPrincipal, doc, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_WEBSOCKET); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/Bindings.conf thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/Bindings.conf --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/Bindings.conf 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/Bindings.conf 2014-11-26 21:45:56.000000000 +0000 @@ -1272,6 +1272,14 @@ 'wrapperCache': False, }], +'VRFieldOfViewReadOnly': { + 'concrete': False +}, + +'VRDevice': { + 'concrete': False +}, + 'VTTCue': { 'nativeType': 'mozilla::dom::TextTrackCue' }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/BindingUtils.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/BindingUtils.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/BindingUtils.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/BindingUtils.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -459,7 +459,7 @@ } if (!JS_DefineProperty(cx, constructor, "length", ctorNargs, - JSPROP_READONLY | JSPROP_PERMANENT)) { + JSPROP_READONLY)) { return nullptr; } @@ -1698,9 +1698,10 @@ { js::AssertSameCompartment(aCx, aObjArg); - // Check if we're near the stack limit before we get anywhere near the - // transplanting code. We use a conservative check since we'll use a little - // more space before we actually hit the critical "can't fail" path. + // Check if we're anywhere near the stack limit before we reach the + // transplanting code, since it has no good way to handle errors. This uses + // the untrusted script limit, which is not strictly necessary since no + // actual script should run. JS_CHECK_RECURSION_CONSERVATIVE(aCx, return NS_ERROR_FAILURE); JS::Rooted aObj(aCx, aObjArg); @@ -2088,7 +2089,9 @@ nsresult rv; nsCOMPtr implISupports = do_CreateInstance(aContractId, &rv); if (!implISupports) { - NS_WARNING("Failed to get JS implementation for contract"); + nsPrintfCString msg("Failed to get JS implementation for contract \"%s\"", + aContractId); + NS_WARNING(msg.get()); aRv.Throw(rv); return; } @@ -2141,7 +2144,7 @@ template static void -NormalizeScalarValueStringInternal(JSContext* aCx, T& aString) +NormalizeUSVStringInternal(JSContext* aCx, T& aString) { char16_t* start = aString.BeginWriting(); // Must use const here because we can't pass char** to UTF16CharEnumerator as @@ -2158,15 +2161,15 @@ } void -NormalizeScalarValueString(JSContext* aCx, nsAString& aString) +NormalizeUSVString(JSContext* aCx, nsAString& aString) { - NormalizeScalarValueStringInternal(aCx, aString); + NormalizeUSVStringInternal(aCx, aString); } void -NormalizeScalarValueString(JSContext* aCx, binding_detail::FakeString& aString) +NormalizeUSVString(JSContext* aCx, binding_detail::FakeString& aString) { - NormalizeScalarValueStringInternal(aCx, aString); + NormalizeUSVStringInternal(aCx, aString); } bool diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/BindingUtils.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/BindingUtils.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/BindingUtils.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/BindingUtils.h 2014-11-26 21:45:56.000000000 +0000 @@ -1923,10 +1923,10 @@ } void -NormalizeScalarValueString(JSContext* aCx, nsAString& aString); +NormalizeUSVString(JSContext* aCx, nsAString& aString); void -NormalizeScalarValueString(JSContext* aCx, binding_detail::FakeString& aString); +NormalizeUSVString(JSContext* aCx, binding_detail::FakeString& aString); template inline bool diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/CallbackObject.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/CallbackObject.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/CallbackObject.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/CallbackObject.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -57,10 +57,6 @@ , mExceptionHandling(aExceptionHandling) , mIsMainThread(NS_IsMainThread()) { - if (mIsMainThread) { - nsContentUtils::EnterMicroTask(); - } - // Compute the caller's subject principal (if necessary) early, before we // do anything that might perturb the relevant state. nsIPrincipal* webIDLCallerPrincipal = nullptr; @@ -274,12 +270,6 @@ mAutoIncumbentScript.reset(); mAutoEntryScript.reset(); - - // It is important that this is the last thing we do, after leaving the - // compartment and undoing all our entry/incumbent script changes - if (mIsMainThread) { - nsContentUtils::LeaveMicroTask(); - } } already_AddRefed diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/Codegen.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/Codegen.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/Codegen.py 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/Codegen.py 2014-11-26 21:45:56.000000000 +0000 @@ -3012,26 +3012,26 @@ if not iface.isExposedInWindow(): exposedInWindowCheck = dedent( """ - if (NS_IsMainThread()) { - return false; - } + MOZ_ASSERT(!NS_IsMainThread(), "Why did we even get called?"); """) body.append(CGGeneric(exposedInWindowCheck)) - if iface.isExposedInAnyWorker() and iface.isExposedOnlyInSomeWorkers(): + if iface.isExposedInSomeButNotAllWorkers(): workerGlobals = sorted(iface.getWorkerExposureSet()) workerCondition = CGList((CGGeneric('strcmp(name, "%s")' % workerGlobal) for workerGlobal in workerGlobals), " && ") exposedInWorkerCheck = fill( """ - if (!NS_IsMainThread()) { - const char* name = js::GetObjectClass(aObj)->name; - if (${workerCondition}) { - return false; - } + const char* name = js::GetObjectClass(aObj)->name; + if (${workerCondition}) { + return false; } """, workerCondition=workerCondition.define()) - body.append(CGGeneric(exposedInWorkerCheck)) + exposedInWorkerCheck = CGGeneric(exposedInWorkerCheck) + if iface.isExposedInWindow(): + exposedInWorkerCheck = CGIfWrapper(exposedInWorkerCheck, + "!NS_IsMainThread()") + body.append(exposedInWorkerCheck) pref = iface.getExtendedAttribute("Pref") if pref: @@ -3474,7 +3474,6 @@ JSAutoCompartment ac(aCx, obj); if (!get_${name}(aCx, obj, aObject, args)) { js::SetReservedSlot(obj, ${slotIndex}, oldValue); - nsJSUtils::ReportPendingException(aCx); return false; } return true; @@ -4838,7 +4837,7 @@ declArgs=declArgs, holderArgs=holderArgs) - if type.isDOMString() or type.isScalarValueString(): + if type.isDOMString() or type.isUSVString(): assert not isEnforceRange and not isClamp treatAs = { @@ -4857,8 +4856,8 @@ def getConversionCode(varName): normalizeCode = "" - if type.isScalarValueString(): - normalizeCode = "NormalizeScalarValueString(cx, %s);\n" % varName + if type.isUSVString(): + normalizeCode = "NormalizeUSVString(cx, %s);\n" % varName conversionCode = ( "if (!ConvertJSValueToString(cx, ${val}, %s, %s, %s)) {\n" @@ -5798,7 +5797,7 @@ wrappingCode += wrapAndSetPtr(wrap, failed) return (wrappingCode, False) - if type.isDOMString() or type.isScalarValueString(): + if type.isDOMString() or type.isUSVString(): if type.nullable(): return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalHandle})" % result), False) else: @@ -6078,7 +6077,7 @@ if returnType.nullable(): result = CGTemplatedType("Nullable", result) return result, None, None, None, None - if returnType.isDOMString() or returnType.isScalarValueString(): + if returnType.isDOMString() or returnType.isUSVString(): if isMember: return CGGeneric("nsString"), "ref", None, None, None return CGGeneric("DOMString"), "ref", None, None, None @@ -8489,7 +8488,7 @@ typeName = CGGeneric(type.name) return CGWrapper(typeName, post=" const &") - if type.isDOMString() or type.isScalarValueString(): + if type.isDOMString() or type.isUSVString(): return CGGeneric("const nsAString&") if type.isByteString(): @@ -11883,6 +11882,7 @@ def definition_body(self): descriptors = self.config.getDescriptors(hasInterfaceObject=True, isExposedInSystemGlobals=True, + workers=False, register=True, skipGen=False) @@ -11958,6 +11958,7 @@ for desc in self.config.getDescriptors(hasInterfaceObject=True, isExternal=False, workers=False, + isExposedInWindow=True, register=True): lines.append("REGISTER_PROTO(%s, %s);\n" % (desc.name, getCheck(desc))) lines.extend("REGISTER_CONSTRUCTOR(%s, %s, %s);\n" % (n.identifier.name, desc.name, getCheck(desc)) @@ -12226,10 +12227,6 @@ workers=True)) != 0 bindingHeaders["WorkerPrivate.h"] = hasWorkerStuff - def descriptorHasThreadChecks(desc): - return ((not desc.workers and not desc.interface.isExposedInWindow()) or - (desc.interface.isExposedInAnyWorker() and desc.interface.isExposedOnlyInSomeWorkers())) - hasThreadChecks = hasWorkerStuff or any(d.hasThreadChecks() for d in descriptors) bindingHeaders["nsThreadUtils.h"] = hasThreadChecks @@ -12471,7 +12468,7 @@ return (result.define(), "%s(%s)" % (result.define(), defaultReturnArg), "return ${declName};\n") - if type.isDOMString() or type.isScalarValueString(): + if type.isDOMString() or type.isUSVString(): if isMember: # No need for a third element in the isMember case return "nsString", None, None @@ -12591,7 +12588,7 @@ def getArgs(self, returnType, argList): args = [self.getArg(arg) for arg in argList] # Now the outparams - if returnType.isDOMString() or returnType.isScalarValueString(): + if returnType.isDOMString() or returnType.isUSVString(): args.append(Argument("nsString&", "aRetVal")) elif returnType.isByteString(): args.append(Argument("nsCString&", "aRetVal")) @@ -12718,7 +12715,7 @@ # Unroll for the name, in case we're nullable. return type.unroll().name, True, True - if type.isDOMString() or type.isScalarValueString(): + if type.isDOMString() or type.isUSVString(): if isMember: declType = "nsString" else: @@ -14400,6 +14397,7 @@ defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface) for desc in config.getDescriptors(hasInterfaceObject=True, workers=False, + isExposedInWindow=True, register=True)] defineIncludes.append('nsScriptNameSpaceManager.h') defineIncludes.extend([CGHeaders.getDeclarationFilename(desc.interface) @@ -14590,7 +14588,7 @@ memberName = CGDictionary.makeMemberName(self.member.identifier.name) if (type.isPrimitive() and type.tag() in builtinNames) or type.isEnum() or type.isGeckoInterface(): return "return " + memberName + ";\n" - if type.isDOMString() or type.isByteString() or type.isScalarValueString(): + if type.isDOMString() or type.isByteString() or type.isUSVString(): return "aRetVal = " + memberName + ";\n" if type.isSpiderMonkeyInterface() or type.isObject(): return fill( @@ -14983,7 +14981,7 @@ nativeType = CGGeneric(type.unroll().inner.identifier.name) if type.nullable(): nativeType = CGTemplatedType("Nullable", nativeType) - elif type.isDOMString() or type.isScalarValueString(): + elif type.isDOMString() or type.isUSVString(): nativeType = CGGeneric("nsString") elif type.isByteString(): nativeType = CGGeneric("nsCString") diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/Configuration.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/Configuration.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/Configuration.py 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/Configuration.py 2014-11-26 21:45:56.000000000 +0000 @@ -210,6 +210,9 @@ elif key == 'isExposedInSystemGlobals': getter = lambda x: (not x.interface.isExternal() and x.interface.isExposedInSystemGlobals()) + elif key == 'isExposedInWindow': + getter = lambda x: (not x.interface.isExternal() and + x.interface.isExposedInWindow()) else: # Have to watch out: just closing over "key" is not enough, # since we're about to mutate its value @@ -654,12 +657,13 @@ in self.interface.members)) def hasThreadChecks(self): - return ((not self.workers and not self.interface.isExposedInWindow()) or - (self.interface.isExposedInAnyWorker() and - self.interface.isExposedOnlyInSomeWorkers())) + return ((self.isExposedConditionally() and + not self.interface.isExposedInWindow()) or + self.interface.isExposedInSomeButNotAllWorkers()) def isExposedConditionally(self): - return self.interface.isExposedConditionally() or self.hasThreadChecks() + return (self.interface.isExposedConditionally() or + self.interface.isExposedInSomeButNotAllWorkers()) def needsXrayResolveHooks(self): """ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/DOMJSProxyHandler.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/DOMJSProxyHandler.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/DOMJSProxyHandler.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/DOMJSProxyHandler.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -268,18 +268,6 @@ } bool -BaseDOMProxyHandler::enumerate(JSContext* cx, JS::Handle proxy, - AutoIdVector& props) const -{ - JS::Rooted proto(cx); - if (!JS_GetPrototype(cx, proxy, &proto)) { - return false; - } - return getOwnEnumerablePropertyKeys(cx, proxy, props) && - (!proto || js::GetPropertyKeys(cx, proto, 0, &props)); -} - -bool BaseDOMProxyHandler::watch(JSContext* cx, JS::Handle proxy, JS::Handle id, JS::Handle callable) const { @@ -309,6 +297,19 @@ } bool +BaseDOMProxyHandler::getEnumerablePropertyKeys(JSContext* cx, + JS::Handle proxy, + AutoIdVector& props) const +{ + JS::Rooted proto(cx); + if (!JS_GetPrototype(cx, proxy, &proto)) { + return false; + } + return getOwnEnumerablePropertyKeys(cx, proxy, props) && + (!proto || js::GetPropertyKeys(cx, proto, 0, &props)); +} + +bool DOMProxyHandler::has(JSContext* cx, JS::Handle proxy, JS::Handle id, bool* bp) const { if (!hasOwn(cx, proxy, id, bp)) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/DOMJSProxyHandler.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/DOMJSProxyHandler.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/DOMJSProxyHandler.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/DOMJSProxyHandler.h 2014-11-26 21:45:56.000000000 +0000 @@ -57,8 +57,6 @@ JS::MutableHandle desc) const MOZ_OVERRIDE; virtual bool ownPropertyKeys(JSContext* cx, JS::Handle proxy, JS::AutoIdVector &props) const MOZ_OVERRIDE; - bool enumerate(JSContext* cx, JS::Handle proxy, - JS::AutoIdVector& props) const MOZ_OVERRIDE; bool getPropertyDescriptor(JSContext* cx, JS::Handle proxy, JS::Handle id, @@ -71,6 +69,8 @@ // unnecessary work during enumeration. virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle proxy, JS::AutoIdVector &props) const MOZ_OVERRIDE; + bool getEnumerablePropertyKeys(JSContext* cx, JS::Handle proxy, + JS::AutoIdVector& props) const MOZ_OVERRIDE; bool watch(JSContext* cx, JS::Handle proxy, JS::Handle id, JS::Handle callable) const MOZ_OVERRIDE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_distinguishability.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_distinguishability.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_distinguishability.py 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_distinguishability.py 2014-11-26 21:45:56.000000000 +0000 @@ -160,7 +160,7 @@ "optional Dict2", "sequence", "sequence", "MozMap", "MozMap", "MozMap", "long[]", "short[]", "Date", "Date?", "any", - "ScalarValueString" ] + "USVString" ] # When we can parse Date and RegExp, we need to add them here. # Try to categorize things a bit to keep list lengths down @@ -171,7 +171,7 @@ primitives = numerics + booleans nonNumerics = allBut(argTypes, numerics) nonBooleans = allBut(argTypes, booleans) - strings = [ "DOMString", "ByteString", "Enum", "Enum2", "ScalarValueString" ] + strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString" ] nonStrings = allBut(argTypes, strings) nonObjects = primitives + strings objects = allBut(argTypes, nonObjects ) @@ -206,7 +206,7 @@ setDistinguishable("boolean?", allBut(nonBooleans, nullables)) setDistinguishable("DOMString", nonStrings) setDistinguishable("ByteString", nonStrings) - setDistinguishable("ScalarValueString", nonStrings) + setDistinguishable("USVString", nonStrings) setDistinguishable("Enum", nonStrings) setDistinguishable("Enum2", nonStrings) setDistinguishable("Interface", notRelatedInterfaces) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_scalarvaluestring.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_scalarvaluestring.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_scalarvaluestring.py 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_scalarvaluestring.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -# -*- coding: UTF-8 -*- - -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestScalarValueString { - attribute ScalarValueString svs; - }; - """) - - results = parser.finish(); - - harness.check(len(results), 1, "Should be one production") - harness.ok(isinstance(results[0], WebIDL.IDLInterface), - "Should be an IDLInterface") - iface = results[0] - harness.check(iface.identifier.QName(), "::TestScalarValueString", - "Interface has the right QName") - harness.check(iface.identifier.name, "TestScalarValueString", - "Interface has the right name") - harness.check(iface.parent, None, "Interface has no parent") - - members = iface.members - harness.check(len(members), 1, "Should be one member") - - attr = members[0] - harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") - harness.check(attr.identifier.QName(), "::TestScalarValueString::svs", - "Attr has correct QName") - harness.check(attr.identifier.name, "svs", "Attr has correct name") - harness.check(str(attr.type), "ScalarValueString", - "Attr type is the correct name") - harness.ok(attr.type.isScalarValueString(), "Should be ScalarValueString type") - harness.ok(attr.type.isString(), "Should be String collective type") - harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type") diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_union.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_union.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_union.py 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_union.py 2014-11-26 21:45:56.000000000 +0000 @@ -63,7 +63,7 @@ "octet", "DOMString", "ByteString", - "ScalarValueString", + "USVString", #"sequence", "object", "ArrayBuffer", diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_usvstring.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_usvstring.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/tests/test_usvstring.py 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/tests/test_usvstring.py 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,36 @@ +# -*- coding: UTF-8 -*- + +import WebIDL + +def WebIDLTest(parser, harness): + parser.parse(""" + interface TestUSVString { + attribute USVString svs; + }; + """) + + results = parser.finish(); + + harness.check(len(results), 1, "Should be one production") + harness.ok(isinstance(results[0], WebIDL.IDLInterface), + "Should be an IDLInterface") + iface = results[0] + harness.check(iface.identifier.QName(), "::TestUSVString", + "Interface has the right QName") + harness.check(iface.identifier.name, "TestUSVString", + "Interface has the right name") + harness.check(iface.parent, None, "Interface has no parent") + + members = iface.members + harness.check(len(members), 1, "Should be one member") + + attr = members[0] + harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") + harness.check(attr.identifier.QName(), "::TestUSVString::svs", + "Attr has correct QName") + harness.check(attr.identifier.name, "svs", "Attr has correct name") + harness.check(str(attr.type), "USVString", + "Attr type is the correct name") + harness.ok(attr.type.isUSVString(), "Should be USVString type") + harness.ok(attr.type.isString(), "Should be String collective type") + harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type") diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/WebIDL.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/WebIDL.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/parser/WebIDL.py 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/parser/WebIDL.py 2014-11-26 21:45:56.000000000 +0000 @@ -1072,8 +1072,15 @@ def isExposedInSystemGlobals(self): return 'BackstagePass' in self.exposureSet - def isExposedOnlyInSomeWorkers(self): - assert self.isExposedInAnyWorker() + def isExposedInSomeButNotAllWorkers(self): + """ + Returns true if the Exposed extended attribute for this interface + exposes it in some worker globals but not others. The return value does + not depend on whether the interface is exposed in Window or System + globals. + """ + if not self.isExposedInAnyWorker(): + return False workerScopes = self.parentScope.globalNameMapping["Worker"] return len(workerScopes.difference(self.exposureSet)) > 0 @@ -1565,7 +1572,7 @@ 'any', 'domstring', 'bytestring', - 'scalarvaluestring', + 'usvstring', 'object', 'date', 'void', @@ -1618,7 +1625,7 @@ def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -1804,8 +1811,8 @@ def isDOMString(self): return self.inner.isDOMString() - def isScalarValueString(self): - return self.inner.isScalarValueString() + def isUSVString(self): + return self.inner.isUSVString() def isFloat(self): return self.inner.isFloat() @@ -1932,7 +1939,7 @@ def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -2206,7 +2213,7 @@ def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -2304,8 +2311,8 @@ def isDOMString(self): return self.inner.isDOMString() - def isScalarValueString(self): - return self.inner.isScalarValueString() + def isUSVString(self): + return self.inner.isUSVString() def isVoid(self): return self.inner.isVoid() @@ -2405,7 +2412,7 @@ def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -2559,7 +2566,7 @@ 'any', 'domstring', 'bytestring', - 'scalarvaluestring', + 'usvstring', 'object', 'date', 'void', @@ -2594,7 +2601,7 @@ Types.any: IDLType.Tags.any, Types.domstring: IDLType.Tags.domstring, Types.bytestring: IDLType.Tags.bytestring, - Types.scalarvaluestring: IDLType.Tags.scalarvaluestring, + Types.usvstring: IDLType.Tags.usvstring, Types.object: IDLType.Tags.object, Types.date: IDLType.Tags.date, Types.void: IDLType.Tags.void, @@ -2628,7 +2635,7 @@ def isString(self): return self._typeTag == IDLBuiltinType.Types.domstring or \ self._typeTag == IDLBuiltinType.Types.bytestring or \ - self._typeTag == IDLBuiltinType.Types.scalarvaluestring + self._typeTag == IDLBuiltinType.Types.usvstring def isByteString(self): return self._typeTag == IDLBuiltinType.Types.bytestring @@ -2636,8 +2643,8 @@ def isDOMString(self): return self._typeTag == IDLBuiltinType.Types.domstring - def isScalarValueString(self): - return self._typeTag == IDLBuiltinType.Types.scalarvaluestring + def isUSVString(self): + return self._typeTag == IDLBuiltinType.Types.usvstring def isInteger(self): return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long @@ -2791,9 +2798,9 @@ IDLBuiltinType.Types.bytestring: IDLBuiltinType(BuiltinLocation(""), "ByteString", IDLBuiltinType.Types.bytestring), - IDLBuiltinType.Types.scalarvaluestring: - IDLBuiltinType(BuiltinLocation(""), "ScalarValueString", - IDLBuiltinType.Types.scalarvaluestring), + IDLBuiltinType.Types.usvstring: + IDLBuiltinType(BuiltinLocation(""), "USVString", + IDLBuiltinType.Types.usvstring), IDLBuiltinType.Types.object: IDLBuiltinType(BuiltinLocation(""), "Object", IDLBuiltinType.Types.object), @@ -2928,10 +2935,10 @@ raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted" % self.value, [location]); return self - elif self.type.isString() and type.isScalarValueString(): - # Allow ScalarValueStrings to use default value just like + elif self.type.isString() and type.isUSVString(): + # Allow USVStrings to use default value just like # DOMString. No coercion is required in this case as Codegen.py - # treats ScalarValueString just like DOMString, but with an + # treats USVString just like DOMString, but with an # extra normalization step. assert self.type.isDOMString() return self @@ -4161,7 +4168,7 @@ "Date": "DATE", "DOMString": "DOMSTRING", "ByteString": "BYTESTRING", - "ScalarValueString": "SCALARVALUESTRING", + "USVString": "USVSTRING", "any": "ANY", "boolean": "BOOLEAN", "byte": "BYTE", @@ -5125,7 +5132,7 @@ | DATE | DOMSTRING | BYTESTRING - | SCALARVALUESTRING + | USVSTRING | ANY | ATTRIBUTE | BOOLEAN @@ -5398,11 +5405,11 @@ """ p[0] = IDLBuiltinType.Types.bytestring - def p_PrimitiveOrStringTypeScalarValueString(self, p): + def p_PrimitiveOrStringTypeUSVString(self, p): """ - PrimitiveOrStringType : SCALARVALUESTRING + PrimitiveOrStringType : USVSTRING """ - p[0] = IDLBuiltinType.Types.scalarvaluestring + p[0] = IDLBuiltinType.Types.usvstring def p_UnsignedIntegerTypeUnsigned(self, p): """ @@ -5695,6 +5702,7 @@ # Builtin IDL defined by WebIDL _builtins = """ typedef unsigned long long DOMTimeStamp; + typedef (ArrayBufferView or ArrayBuffer) BufferSource; """ def main(): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/mochitest.ini 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/mochitest.ini 2014-11-26 21:45:56.000000000 +0000 @@ -44,7 +44,7 @@ [test_queryInterface.html] [test_returnUnion.html] skip-if = debug == false -[test_scalarvaluestring.html] +[test_usvstring.html] skip-if = debug == false [test_sequence_wrapping.html] [test_setWithNamedGetterNoNamedSetter.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestBindingHeader.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestBindingHeader.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestBindingHeader.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestBindingHeader.h 2014-11-26 21:45:56.000000000 +0000 @@ -480,15 +480,15 @@ void PassOptionalNullableByteString(const Optional&); void PassVariadicByteString(const Sequence&); - // ScalarValueString types - void PassSVS(const nsAString&); - void PassNullableSVS(const nsAString&); - void PassOptionalSVS(const Optional&); - void PassOptionalSVSWithDefaultValue(const nsAString&); - void PassOptionalNullableSVS(const Optional&); - void PassOptionalNullableSVSWithDefaultValue(const nsAString&); - void PassVariadicSVS(const Sequence&); - void ReceiveSVS(DOMString&); + // USVString types + void PassUSVS(const nsAString&); + void PassNullableUSVS(const nsAString&); + void PassOptionalUSVS(const Optional&); + void PassOptionalUSVSWithDefaultValue(const nsAString&); + void PassOptionalNullableUSVS(const Optional&); + void PassOptionalNullableUSVSWithDefaultValue(const nsAString&); + void PassVariadicUSVS(const Sequence&); + void ReceiveUSVS(DOMString&); // Enumerated types void PassEnum(TestEnum); @@ -613,7 +613,7 @@ void PassUnionWithMozMap(const StringMozMapOrString&); void PassUnionWithMozMapAndSequence(const StringMozMapOrStringSequence&); void PassUnionWithSequenceAndMozMap(const StringSequenceOrStringMozMap&); - void PassUnionWithSVS(const ScalarValueStringOrLong&); + void PassUnionWithUSVS(const USVStringOrLong&); #endif void PassNullableUnion(JSContext*, const Nullable&); void PassOptionalUnion(JSContext*, const Optional&); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestCodeGen.webidl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestCodeGen.webidl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestCodeGen.webidl 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestCodeGen.webidl 2014-11-26 21:45:56.000000000 +0000 @@ -460,15 +460,15 @@ void passOptionalNullableByteString(optional ByteString? arg); void passVariadicByteString(ByteString... arg); - // ScalarValueString types - void passSVS(ScalarValueString arg); - void passNullableSVS(ScalarValueString? arg); - void passOptionalSVS(optional ScalarValueString arg); - void passOptionalSVSWithDefaultValue(optional ScalarValueString arg = "abc"); - void passOptionalNullableSVS(optional ScalarValueString? arg); - void passOptionalNullableSVSWithDefaultValue(optional ScalarValueString? arg = null); - void passVariadicSVS(ScalarValueString... arg); - ScalarValueString receiveSVS(); + // USVString types + void passUSVS(USVString arg); + void passNullableUSVS(USVString? arg); + void passOptionalUSVS(optional USVString arg); + void passOptionalUSVSWithDefaultValue(optional USVString arg = "abc"); + void passOptionalNullableUSVS(optional USVString? arg); + void passOptionalNullableUSVSWithDefaultValue(optional USVString? arg = null); + void passVariadicUSVS(USVString... arg); + USVString receiveUSVS(); // Enumerated types void passEnum(TestEnum arg); @@ -578,7 +578,7 @@ void passUnionWithMozMap((MozMap or DOMString) arg); void passUnionWithMozMapAndSequence((MozMap or sequence) arg); void passUnionWithSequenceAndMozMap((sequence or MozMap) arg); - void passUnionWithSVS((ScalarValueString or long) arg); + void passUnionWithUSVS((USVString or long) arg); #endif void passUnionWithNullable((object? or long) arg); void passNullableUnion((object or long)? arg); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestExampleGen.webidl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestExampleGen.webidl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestExampleGen.webidl 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestExampleGen.webidl 2014-11-26 21:45:56.000000000 +0000 @@ -327,15 +327,15 @@ void passVariadicByteString(ByteString... arg); void passUnionByteString((ByteString or long) arg); - // ScalarValueString types - void passSVS(ScalarValueString arg); - void passNullableSVS(ScalarValueString? arg); - void passOptionalSVS(optional ScalarValueString arg); - void passOptionalSVSWithDefaultValue(optional ScalarValueString arg = "abc"); - void passOptionalNullableSVS(optional ScalarValueString? arg); - void passOptionalNullableSVSWithDefaultValue(optional ScalarValueString? arg = null); - void passVariadicSVS(ScalarValueString... arg); - ScalarValueString receiveSVS(); + // USVString types + void passSVS(USVString arg); + void passNullableSVS(USVString? arg); + void passOptionalSVS(optional USVString arg); + void passOptionalSVSWithDefaultValue(optional USVString arg = "abc"); + void passOptionalNullableSVS(optional USVString? arg); + void passOptionalNullableSVSWithDefaultValue(optional USVString? arg = null); + void passVariadicSVS(USVString... arg); + USVString receiveSVS(); // Enumerated types void passEnum(TestEnum arg); @@ -443,7 +443,7 @@ void passUnionWithMozMap((MozMap or DOMString) arg); void passUnionWithMozMapAndSequence((MozMap or sequence) arg); void passUnionWithSequenceAndMozMap((sequence or MozMap) arg); - void passUnionWithSVS((ScalarValueString or long) arg); + void passUnionWithSVS((USVString or long) arg); #endif void passUnionWithNullable((object? or long) arg); void passNullableUnion((object or long)? arg); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/test_exception_messages.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/test_exception_messages.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/test_exception_messages.html 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/test_exception_messages.html 2014-11-26 21:45:56.000000000 +0000 @@ -44,8 +44,8 @@ [ 'document.createTreeWalker(document, 0xFFFFFFFF, { acceptNode: 5 }).nextNode()', "Property 'acceptNode' is not callable.", "non-callable callback interface operation property" ], - [ '(new TextEncoder).encode("", new RegExp())', - "Argument 2 of TextEncoder.encode can't be converted to a dictionary.", + [ '(new TextDecoder).decode(new Uint8Array(), new RegExp())', + "Argument 2 of TextDecoder.decode can't be converted to a dictionary.", "regexp passed for a dictionary" ], [ 'URL.createObjectURL(null, null)', "Argument 1 is not valid for any of the 2-argument overloads of URL.createObjectURL.", diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestJSImplGen.webidl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestJSImplGen.webidl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/TestJSImplGen.webidl 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/TestJSImplGen.webidl 2014-11-26 21:45:56.000000000 +0000 @@ -339,15 +339,15 @@ void passVariadicByteString(ByteString... arg); void PassUnionByteString((ByteString or long) arg); - // ScalarValueString types - void passSVS(ScalarValueString arg); - void passNullableSVS(ScalarValueString? arg); - void passOptionalSVS(optional ScalarValueString arg); - void passOptionalSVSWithDefaultValue(optional ScalarValueString arg = "abc"); - void passOptionalNullableSVS(optional ScalarValueString? arg); - void passOptionalNullableSVSWithDefaultValue(optional ScalarValueString? arg = null); - void passVariadicSVS(ScalarValueString... arg); - ScalarValueString receiveSVS(); + // USVString types + void passSVS(USVString arg); + void passNullableSVS(USVString? arg); + void passOptionalSVS(optional USVString arg); + void passOptionalSVSWithDefaultValue(optional USVString arg = "abc"); + void passOptionalNullableSVS(optional USVString? arg); + void passOptionalNullableSVSWithDefaultValue(optional USVString? arg = null); + void passVariadicSVS(USVString... arg); + USVString receiveSVS(); // Enumerated types void passEnum(MyTestEnum arg); @@ -456,7 +456,7 @@ void passUnionWithMozMap((MozMap or DOMString) arg); void passUnionWithMozMapAndSequence((MozMap or sequence) arg); void passUnionWithSequenceAndMozMap((sequence or MozMap) arg); - void passUnionWithSVS((ScalarValueString or long) arg); + void passUnionWithSVS((USVString or long) arg); #endif void passUnionWithNullable((object? or long) arg); void passNullableUnion((object or long)? arg); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/test_scalarvaluestring.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/test_scalarvaluestring.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/test_scalarvaluestring.html 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/test_scalarvaluestring.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ - - - - - Test ScalarValueString - - - - - - - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/test_usvstring.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/test_usvstring.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/test/test_usvstring.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/test/test_usvstring.html 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,41 @@ + + + + + Test USVString + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/ToJSValue.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/ToJSValue.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/ToJSValue.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/ToJSValue.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -66,10 +66,10 @@ JS::MutableHandle aValue) { MOZ_ASSERT(aArgument.Failed()); - ThrowMethodFailedWithDetails(aCx, aArgument, "", ""); - if (!JS_GetPendingException(aCx, aValue)) { - return false; - } + DebugOnly throwResult = ThrowMethodFailedWithDetails(aCx, aArgument, "", ""); + MOZ_ASSERT(!throwResult); + DebugOnly getPendingResult = JS_GetPendingException(aCx, aValue); + MOZ_ASSERT(getPendingResult); JS_ClearPendingException(aCx); return true; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/ToJSValue.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/ToJSValue.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bindings/ToJSValue.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bindings/ToJSValue.h 2014-11-26 21:45:56.000000000 +0000 @@ -138,11 +138,10 @@ return MaybeWrapValue(aCx, aValue); } -// Accept objects that inherit from nsWrapperCache and nsISupports (e.g. most +// Accept objects that inherit from nsWrapperCache (e.g. most // DOM objects). template -typename EnableIf::value && - IsBaseOf::value, bool>::Type +typename EnableIf::value, bool>::Type ToJSValue(JSContext* aCx, T& aArgument, JS::MutableHandle aValue) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,1240 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "BluetoothDaemonHandsfreeInterface.h" +#include "BluetoothDaemonSetupInterface.h" +#include "mozilla/unused.h" + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Handsfree module +// + +BluetoothHandsfreeNotificationHandler* + BluetoothDaemonHandsfreeModule::sNotificationHandler; + +void +BluetoothDaemonHandsfreeModule::SetNotificationHandler( + BluetoothHandsfreeNotificationHandler* aNotificationHandler) +{ + sNotificationHandler = aNotificationHandler; +} + +nsresult +BluetoothDaemonHandsfreeModule::Send(BluetoothDaemonPDU* aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + aRes->AddRef(); // Keep reference for response + return Send(aPDU, static_cast(aRes)); +} + +void +BluetoothDaemonHandsfreeModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) +{ + static void (BluetoothDaemonHandsfreeModule::* const HandleOp[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + INIT_ARRAY_AT(0, &BluetoothDaemonHandsfreeModule::HandleRsp), + INIT_ARRAY_AT(1, &BluetoothDaemonHandsfreeModule::HandleNtf), + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + // Negate twice to map bit to 0/1 + unsigned long isNtf = !!(aHeader.mOpcode & 0x80); + + (this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData); +} + +// Commands +// + +nsresult +BluetoothDaemonHandsfreeModule::ConnectCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONNECT, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::DisconnectCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISCONNECT, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::ConnectAudioCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONNECT_AUDIO, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::DisconnectAudioCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISCONNECT_AUDIO, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::StartVoiceRecognitionCmd( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION, + 0)); // No payload + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::StopVoiceRecognitionCmd( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION, + 0)); // No payload + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::VolumeControlCmd( + BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_VOLUME_CONTROL, + 1 + // Volume type + 1)); // Volume + + nsresult rv = PackPDU(aType, PackConversion(aVolume), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::DeviceStatusNotificationCmd( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DEVICE_STATUS_NOTIFICATION, + 1 + // Network state + 1 + // Service type + 1 + // Signal strength + 1)); // Battery level + + nsresult rv = PackPDU(aNtkState, aSvcType, + PackConversion(aSignal), + PackConversion(aBattChg), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::CopsResponseCmd( + const char* aCops, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_COPS_RESPONSE, + 0)); // Dynamically allocated + + nsresult rv = PackPDU(PackCString0(nsDependentCString(aCops)), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::CindResponseCmd( + int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CIND_RESPONSE, + 1 + // Service + 1 + // # Active + 1 + // # Held + 1 + // Call state + 1 + // Signal strength + 1 + // Roaming + 1)); // Battery level + + nsresult rv = PackPDU(PackConversion(aSvc), + PackConversion(aNumActive), + PackConversion(aNumHeld), + aCallSetupState, + PackConversion(aSignal), + PackConversion(aRoam), + PackConversion(aBattChg), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::FormattedAtResponseCmd( + const char* aRsp, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE, + 0)); // Dynamically allocated + + nsresult rv = PackPDU(PackCString0(nsDependentCString(aRsp)), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::AtResponseCmd( + BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_AT_RESPONSE, + 1 + // AT Response code + 1)); // Error code + + nsresult rv = PackPDU(aResponseCode, + PackConversion(aErrorCode), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::ClccResponseCmd( + int aIndex, + BluetoothHandsfreeCallDirection aDir, BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + NS_ConvertUTF16toUTF8 number(aNumber); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLCC_RESPONSE, + 1 + // Call index + 1 + // Call direction + 1 + // Call state + 1 + // Call mode + 1 + // Call MPTY + 1 + // Address type + number.Length() + 1)); // Number string + \0 + + nsresult rv = PackPDU(PackConversion(aIndex), + aDir, aState, aMode, aMpty, aType, + PackCString0(number), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::PhoneStateChangeCmd( + int aNumActive, int aNumHeld, BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + NS_ConvertUTF16toUTF8 number(aNumber); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_PHONE_STATE_CHANGE, + 1 + // # Active + 1 + // # Held + 1 + // Call state + 1 + // Address type + number.Length() + 1)); // Number string + \0 + + nsresult rv = PackPDU(PackConversion(aNumActive), + PackConversion(aNumHeld), + aCallSetupState, aType, + PackCString0(NS_ConvertUTF16toUTF8(aNumber)), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +// Responses +// + +void +BluetoothDaemonHandsfreeModule::ErrorRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ConnectRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::Connect, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DisconnectRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::Disconnect, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ConnectAudioRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::ConnectAudio, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DisconnectAudioRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::StartVoiceRecognitionRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::StopVoiceRecognitionRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::VolumeControlRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::VolumeControl, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DeviceStatusNotificationRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CopsResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::CopsResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CindResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::CindResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::FormattedAtResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::AtResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::AtResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ClccResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::ClccResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::PhoneStateChangeRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::HandleRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonHandsfreeModule::* const HandleRsp[])( + const BluetoothDaemonPDUHeader&, + BluetoothDaemonPDU&, + BluetoothHandsfreeResultHandler*) = { + INIT_ARRAY_AT(OPCODE_ERROR, + &BluetoothDaemonHandsfreeModule::ErrorRsp), + INIT_ARRAY_AT(OPCODE_CONNECT, + &BluetoothDaemonHandsfreeModule::ConnectRsp), + INIT_ARRAY_AT(OPCODE_DISCONNECT, + &BluetoothDaemonHandsfreeModule::DisconnectRsp), + INIT_ARRAY_AT(OPCODE_CONNECT_AUDIO, + &BluetoothDaemonHandsfreeModule::ConnectAudioRsp), + INIT_ARRAY_AT(OPCODE_DISCONNECT_AUDIO, + &BluetoothDaemonHandsfreeModule::DisconnectAudioRsp), + INIT_ARRAY_AT(OPCODE_START_VOICE_RECOGNITION, + &BluetoothDaemonHandsfreeModule::StartVoiceRecognitionRsp), + INIT_ARRAY_AT(OPCODE_STOP_VOICE_RECOGNITION, + &BluetoothDaemonHandsfreeModule::StopVoiceRecognitionRsp), + INIT_ARRAY_AT(OPCODE_VOLUME_CONTROL, + &BluetoothDaemonHandsfreeModule::VolumeControlRsp), + INIT_ARRAY_AT(OPCODE_DEVICE_STATUS_NOTIFICATION, + &BluetoothDaemonHandsfreeModule::DeviceStatusNotificationRsp), + INIT_ARRAY_AT(OPCODE_COPS_RESPONSE, + &BluetoothDaemonHandsfreeModule::CopsResponseRsp), + INIT_ARRAY_AT(OPCODE_CIND_RESPONSE, + &BluetoothDaemonHandsfreeModule::CindResponseRsp), + INIT_ARRAY_AT(OPCODE_FORMATTED_AT_RESPONSE, + &BluetoothDaemonHandsfreeModule::FormattedAtResponseRsp), + INIT_ARRAY_AT(OPCODE_AT_RESPONSE, + &BluetoothDaemonHandsfreeModule::AtResponseRsp), + INIT_ARRAY_AT(OPCODE_CLCC_RESPONSE, + &BluetoothDaemonHandsfreeModule::ClccResponseRsp), + INIT_ARRAY_AT(OPCODE_PHONE_STATE_CHANGE, + &BluetoothDaemonHandsfreeModule::PhoneStateChangeRsp) + }; + + MOZ_ASSERT(!NS_IsMainThread()); // I/O thread + + if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + + if (!res) { + return; // Return early if no result handler has been set for response + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +// Notifications +// + +// Returns the current notification handler to a notification runnable +class BluetoothDaemonHandsfreeModule::NotificationHandlerWrapper MOZ_FINAL +{ +public: + typedef BluetoothHandsfreeNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } +}; + +// Init operator class for ConnectionStateNotification +class BluetoothDaemonHandsfreeModule::ConnectionStateInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + ConnectionStateInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothHandsfreeConnectionState& aArg1, + nsString& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read state */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::ConnectionStateNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + ConnectionStateNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification, + ConnectionStateInitOp(aPDU)); +} + +// Init operator class for AudioStateNotification +class BluetoothDaemonHandsfreeModule::AudioStateInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + AudioStateInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothHandsfreeAudioState& aArg1, + nsString& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read state */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::AudioStateNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + AudioStateNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AudioStateNotification, + AudioStateInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + VoiceRecognitionNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::AnswerCallNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + AnswerCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AnswerCallNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::HangupCallNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + HangupCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::HangupCallNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for VolumeNotification +class BluetoothDaemonHandsfreeModule::VolumeInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + VolumeInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothHandsfreeVolumeType& aArg1, int& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read volume type */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read volume */ + rv = UnpackPDU(pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::VolumeNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + VolumeNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VolumeNotification, + VolumeInitOp(aPDU)); +} + +// Init operator class for DialCallNotification +class BluetoothDaemonHandsfreeModule::DialCallInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + DialCallInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1) const + { + /* Read number */ + nsresult rv = UnpackPDU(GetPDU(), UnpackString0(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::DialCallNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + DialCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DialCallNotification, + DialCallInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DtmfNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + DtmfNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DtmfNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::NRECNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + NRECNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::NRECNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CallHoldNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CallHoldNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CallHoldNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CnumNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CnumNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CnumNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CindNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CindNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CindNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CopsNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CopsNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CopsNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ClccNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + ClccNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ClccNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for UnknownAtNotification +class BluetoothDaemonHandsfreeModule::UnknownAtInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + UnknownAtInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsCString& aArg1) const + { + /* Read string */ + nsresult rv = UnpackPDU(GetPDU(), UnpackCString0(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::UnknownAtNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + UnknownAtNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, + UnknownAtInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::KeyPressedNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + KeyPressedNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::KeyPressedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::HandleNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonHandsfreeModule::* const HandleNtf[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + INIT_ARRAY_AT(0, &BluetoothDaemonHandsfreeModule::ConnectionStateNtf), + INIT_ARRAY_AT(1, &BluetoothDaemonHandsfreeModule::AudioStateNtf), + INIT_ARRAY_AT(2, &BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf), + INIT_ARRAY_AT(3, &BluetoothDaemonHandsfreeModule::AnswerCallNtf), + INIT_ARRAY_AT(4, &BluetoothDaemonHandsfreeModule::HangupCallNtf), + INIT_ARRAY_AT(5, &BluetoothDaemonHandsfreeModule::VolumeNtf), + INIT_ARRAY_AT(6, &BluetoothDaemonHandsfreeModule::DialCallNtf), + INIT_ARRAY_AT(7, &BluetoothDaemonHandsfreeModule::DtmfNtf), + INIT_ARRAY_AT(8, &BluetoothDaemonHandsfreeModule::NRECNtf), + INIT_ARRAY_AT(9, &BluetoothDaemonHandsfreeModule::CallHoldNtf), + INIT_ARRAY_AT(10, &BluetoothDaemonHandsfreeModule::CnumNtf), + INIT_ARRAY_AT(11, &BluetoothDaemonHandsfreeModule::CindNtf), + INIT_ARRAY_AT(12, &BluetoothDaemonHandsfreeModule::CopsNtf), + INIT_ARRAY_AT(13, &BluetoothDaemonHandsfreeModule::ClccNtf), + INIT_ARRAY_AT(14, &BluetoothDaemonHandsfreeModule::UnknownAtNtf), + INIT_ARRAY_AT(15, &BluetoothDaemonHandsfreeModule::KeyPressedNtf) + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + uint8_t index = aHeader.mOpcode - 0x81; + + if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) || + NS_WARN_IF(!HandleNtf[index])) { + return; + } + + (this->*(HandleNtf[index]))(aHeader, aPDU); +} + +// +// Handsfree interface +// + +BluetoothDaemonHandsfreeInterface::BluetoothDaemonHandsfreeInterface( + BluetoothDaemonHandsfreeModule* aModule) + : mModule(aModule) +{ } + +BluetoothDaemonHandsfreeInterface::~BluetoothDaemonHandsfreeInterface() +{ } + +class BluetoothDaemonHandsfreeInterface::InitResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + InitResultHandler(BluetoothHandsfreeResultHandler* aRes) + : mRes(aRes) + { + MOZ_ASSERT(mRes); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + mRes->OnError(aStatus); + } + + void RegisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + mRes->Init(); + } + +private: + nsRefPtr mRes; +}; + +void +BluetoothDaemonHandsfreeInterface::Init( + BluetoothHandsfreeNotificationHandler* aNotificationHandler, + BluetoothHandsfreeResultHandler* aRes) +{ + // Set notification handler _before_ registering the module. It could + // happen that we receive notifications, before the result handler runs. + mModule->SetNotificationHandler(aNotificationHandler); + + InitResultHandler* res; + + if (aRes) { + res = new InitResultHandler(aRes); + } else { + // We don't need a result handler if the caller is not interested. + res = nullptr; + } + + nsresult rv = mModule->RegisterModule( + BluetoothDaemonHandsfreeModule::SERVICE_ID, MODE_NARROWBAND_SPEECH, res); + + if (NS_FAILED(rv) && aRes) { + DispatchError(aRes, STATUS_FAIL); + } +} + +class BluetoothDaemonHandsfreeInterface::CleanupResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + CleanupResultHandler(BluetoothDaemonHandsfreeModule* aModule, + BluetoothHandsfreeResultHandler* aRes) + : mModule(aModule) + , mRes(aRes) + { + MOZ_ASSERT(mModule); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + if (mRes) { + mRes->OnError(aStatus); + } + } + + void UnregisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + // Clear notification handler _after_ module has been + // unregistered. While unregistering the module, we might + // still receive notifications. + mModule->SetNotificationHandler(nullptr); + + if (mRes) { + mRes->Cleanup(); + } + } + +private: + BluetoothDaemonHandsfreeModule* mModule; + nsRefPtr mRes; +}; + +void +BluetoothDaemonHandsfreeInterface::Cleanup( + BluetoothHandsfreeResultHandler* aRes) +{ + mModule->UnregisterModule(BluetoothDaemonHandsfreeModule::SERVICE_ID, + new CleanupResultHandler(mModule, aRes)); +} + +/* Connect / Disconnect */ + +void +BluetoothDaemonHandsfreeInterface::Connect( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ConnectCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::Disconnect( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->DisconnectCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::ConnectAudio( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ConnectAudioCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::DisconnectAudio( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->DisconnectAudioCmd(aBdAddr, aRes); +} + +/* Voice Recognition */ + +void +BluetoothDaemonHandsfreeInterface::StartVoiceRecognition( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->StartVoiceRecognitionCmd(aRes); +} + +void +BluetoothDaemonHandsfreeInterface::StopVoiceRecognition( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->StopVoiceRecognitionCmd(aRes); +} + +/* Volume */ + +void +BluetoothDaemonHandsfreeInterface::VolumeControl( + BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->VolumeControlCmd(aType, aVolume, aRes); +} + +/* Device status */ + +void +BluetoothDaemonHandsfreeInterface::DeviceStatusNotification( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->DeviceStatusNotificationCmd(aNtkState, aSvcType, aSignal, + aBattChg, aRes); +} + +/* Responses */ + +void +BluetoothDaemonHandsfreeInterface::CopsResponse( + const char* aCops, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->CopsResponseCmd(aCops, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::CindResponse( + int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld, aCallSetupState, + aSignal, aRoam, aBattChg, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::FormattedAtResponse( + const char* aRsp, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->FormattedAtResponseCmd(aRsp, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::AtResponse( + BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->AtResponseCmd(aResponseCode, aErrorCode, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::ClccResponse( + int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ClccResponseCmd(aIndex, aDir, aState, aMode, aMpty, aNumber, + aType, aRes); +} + +/* Phone State */ + +void +BluetoothDaemonHandsfreeInterface::PhoneStateChange( + int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->PhoneStateChangeCmd(aNumActive, aNumHeld, aCallSetupState, aNumber, + aType, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::DispatchError( + BluetoothHandsfreeResultHandler* aRes, BluetoothStatus aStatus) +{ + BluetoothResultRunnable1::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::OnError, + ConstantInitOp1(aStatus)); +} + +END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,412 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluetoothdaemonhandsfreeinterface_h +#define mozilla_dom_bluetooth_bluetoothdaemonhandsfreeinterface_h + +#include "BluetoothDaemonHelpers.h" +#include "BluetoothInterface.h" +#include "BluetoothInterfaceHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothSetupResultHandler; + +class BluetoothDaemonHandsfreeModule +{ +public: + enum { + SERVICE_ID = 0x05 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_CONNECT = 0x01, + OPCODE_DISCONNECT = 0x02, + OPCODE_CONNECT_AUDIO = 0x03, + OPCODE_DISCONNECT_AUDIO = 0x04, + OPCODE_START_VOICE_RECOGNITION = 0x05, + OPCODE_STOP_VOICE_RECOGNITION =0x06, + OPCODE_VOLUME_CONTROL = 0x07, + OPCODE_DEVICE_STATUS_NOTIFICATION = 0x08, + OPCODE_COPS_RESPONSE = 0x09, + OPCODE_CIND_RESPONSE = 0x0a, + OPCODE_FORMATTED_AT_RESPONSE = 0x0b, + OPCODE_AT_RESPONSE = 0x0c, + OPCODE_CLCC_RESPONSE = 0x0d, + OPCODE_PHONE_STATE_CHANGE = 0x0e + }; + + virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + + virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) = 0; + + virtual nsresult UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) = 0; + + void SetNotificationHandler( + BluetoothHandsfreeNotificationHandler* aNotificationHandler); + + // + // Commands + // + + nsresult ConnectCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + nsresult DisconnectCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + nsresult ConnectAudioCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + nsresult DisconnectAudioCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + + /* Voice Recognition */ + + nsresult StartVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes); + nsresult StopVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes); + + /* Volume */ + + nsresult VolumeControlCmd(BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes); + + /* Device status */ + + nsresult DeviceStatusNotificationCmd( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, + int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + + /* Responses */ + + nsresult CopsResponseCmd(const char* aCops, + BluetoothHandsfreeResultHandler* aRes); + nsresult CindResponseCmd(int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + nsresult FormattedAtResponseCmd(const char* aRsp, + BluetoothHandsfreeResultHandler* aRes); + nsresult AtResponseCmd(BluetoothHandsfreeAtResponse aResponseCode, + int aErrorCode, + BluetoothHandsfreeResultHandler* aRes); + nsresult ClccResponseCmd(int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + + /* Phone State */ + + nsresult PhoneStateChangeCmd(int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + +protected: + nsresult Send(BluetoothDaemonPDU* aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + + // + // Responses + // + + typedef BluetoothResultRunnable0 + ResultRunnable; + + typedef BluetoothResultRunnable1 + ErrorRunnable; + + void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void DisconnectRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void ConnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void DisconnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void StartVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void StopVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void VolumeControlRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void DeviceStatusNotificationRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void CopsResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void CindResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void FormattedAtResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void AtResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void ClccResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void PhoneStateChangeRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData); + + // + // Notifications + // + + class NotificationHandlerWrapper; + + typedef BluetoothNotificationRunnable2 + ConnectionStateNotification; + + typedef BluetoothNotificationRunnable2 + AudioStateNotification; + + typedef BluetoothNotificationRunnable1 + VoiceRecognitionNotification; + + typedef BluetoothNotificationRunnable0 + AnswerCallNotification; + + typedef BluetoothNotificationRunnable0 + HangupCallNotification; + + typedef BluetoothNotificationRunnable2 + VolumeNotification; + + typedef BluetoothNotificationRunnable1 + DialCallNotification; + + typedef BluetoothNotificationRunnable1 + DtmfNotification; + + typedef BluetoothNotificationRunnable1 + NRECNotification; + + typedef BluetoothNotificationRunnable1 + CallHoldNotification; + + typedef BluetoothNotificationRunnable0 + CnumNotification; + + typedef BluetoothNotificationRunnable0 + CindNotification; + + typedef BluetoothNotificationRunnable0 + CopsNotification; + + typedef BluetoothNotificationRunnable0 + ClccNotification; + + typedef BluetoothNotificationRunnable1 + UnknownAtNotification; + + typedef BluetoothNotificationRunnable0 + KeyPressedNotification; + + class AudioStateInitOp; + class ConnectionStateInitOp; + class DialCallInitOp; + class VolumeInitOp; + class UnknownAtInitOp; + + void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void VoiceRecognitionNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void AnswerCallNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void HangupCallNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void VolumeNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void DialCallNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void DtmfNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void NRECNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CallHoldNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CnumNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CindNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CopsNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void ClccNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void UnknownAtNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void KeyPressedNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData); + + static BluetoothHandsfreeNotificationHandler* sNotificationHandler; +}; + +class BluetoothDaemonHandsfreeInterface MOZ_FINAL + : public BluetoothHandsfreeInterface +{ + class CleanupResultHandler; + class InitResultHandler; + + enum { + MODE_HEADSET = 0x00, + MODE_NARROWBAND_SPEECH = 0x01, + MODE_NARRAWBAND_WIDEBAND_SPEECH = 0x02 + }; + +public: + BluetoothDaemonHandsfreeInterface(BluetoothDaemonHandsfreeModule* aModule); + ~BluetoothDaemonHandsfreeInterface(); + + void Init( + BluetoothHandsfreeNotificationHandler* aNotificationHandler, + BluetoothHandsfreeResultHandler* aRes); + void Cleanup(BluetoothHandsfreeResultHandler* aRes); + + /* Connect / Disconnect */ + + void Connect(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void Disconnect(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void ConnectAudio(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void DisconnectAudio(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + + /* Voice Recognition */ + + void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); + void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); + + /* Volume */ + + void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes); + + /* Device status */ + + void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, + int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + + /* Responses */ + + void CopsResponse(const char* aCops, + BluetoothHandsfreeResultHandler* aRes); + void CindResponse(int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + void FormattedAtResponse(const char* aRsp, + BluetoothHandsfreeResultHandler* aRes); + void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes); + void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + + /* Phone State */ + + void PhoneStateChange(int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + +private: + void DispatchError(BluetoothHandsfreeResultHandler* aRes, + BluetoothStatus aStatus); + + BluetoothDaemonHandsfreeModule* mModule; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -46,6 +46,18 @@ } nsresult +Convert(int aIn, uint8_t& aOut) +{ + if (NS_WARN_IF(aIn < std::numeric_limits::min()) || + NS_WARN_IF(aIn > std::numeric_limits::max())) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult Convert(int aIn, int16_t& aOut) { if (NS_WARN_IF(aIn < std::numeric_limits::min()) || @@ -72,6 +84,20 @@ } nsresult +Convert(uint8_t aIn, char& aOut) +{ + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, int& aOut) +{ + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult Convert(uint8_t aIn, BluetoothAclState& aOut) { static const BluetoothAclState sAclState[] = { @@ -101,6 +127,97 @@ } nsresult +Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut) +{ + static const BluetoothHandsfreeAudioState sAudioState[] = { + CONVERT(0x00, HFP_AUDIO_STATE_DISCONNECTED), + CONVERT(0x01, HFP_AUDIO_STATE_CONNECTING), + CONVERT(0x02, HFP_AUDIO_STATE_CONNECTED), + CONVERT(0x03, HFP_AUDIO_STATE_DISCONNECTING) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAudioState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAudioState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeCallHoldType& aOut) +{ + static const BluetoothHandsfreeCallHoldType sCallHoldType[] = { + CONVERT(0x00, HFP_CALL_HOLD_RELEASEHELD), + CONVERT(0x01, HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD), + CONVERT(0x02, HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD), + CONVERT(0x03, HFP_CALL_HOLD_ADDHELDTOCONF) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallHoldType))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallHoldType[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeConnectionState& aOut) +{ + static const BluetoothHandsfreeConnectionState sConnectionState[] = { + CONVERT(0x00, HFP_CONNECTION_STATE_DISCONNECTED), + CONVERT(0x01, HFP_CONNECTION_STATE_CONNECTING), + CONVERT(0x02, HFP_CONNECTION_STATE_CONNECTED), + CONVERT(0x03, HFP_CONNECTION_STATE_SLC_CONNECTED), + CONVERT(0x04, HFP_CONNECTION_STATE_DISCONNECTING) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sConnectionState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sConnectionState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeNRECState& aOut) +{ + static const BluetoothHandsfreeNRECState sNRECState[] = { + CONVERT(0x00, HFP_NREC_STOPPED), + CONVERT(0x01, HFP_NREC_STARTED) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sNRECState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNRECState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut) +{ + static const BluetoothHandsfreeVoiceRecognitionState sState[] = { + CONVERT(0x00, HFP_VOICE_RECOGNITION_STOPPED), + CONVERT(0x01, HFP_VOICE_RECOGNITION_STOPPED) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVolumeType& aOut) +{ + static const BluetoothHandsfreeVolumeType sVolumeType[] = { + CONVERT(0x00, HFP_VOLUME_TYPE_SPEAKER), + CONVERT(0x01, HFP_VOLUME_TYPE_MICROPHONE) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVolumeType[aIn]; + return NS_OK; +} + +nsresult Convert(int32_t aIn, BluetoothDeviceType& aOut) { static const BluetoothDeviceType sDeviceType[] = { @@ -374,6 +491,147 @@ } nsresult +Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut) +{ + static const uint8_t sAtResponse[] = { + CONVERT(HFP_AT_RESPONSE_ERROR, 0x00), + CONVERT(HFP_AT_RESPONSE_OK, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAtResponse))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAtResponse[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut) +{ + static const uint8_t sCallAddressType[] = { + CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, 0x81), + CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL, 0x91) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallAddressType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallAddressType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut) +{ + static const uint8_t sCallDirection[] = { + CONVERT(HFP_CALL_DIRECTION_OUTGOING, 0x00), + CONVERT(HFP_CALL_DIRECTION_INCOMING, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallDirection))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallDirection[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallState aIn, uint8_t& aOut) +{ + static const uint8_t sCallState[] = { + CONVERT(HFP_CALL_STATE_ACTIVE, 0x00), + CONVERT(HFP_CALL_STATE_HELD, 0x01), + CONVERT(HFP_CALL_STATE_DIALING, 0x02), + CONVERT(HFP_CALL_STATE_ALERTING, 0x03), + CONVERT(HFP_CALL_STATE_INCOMING, 0x04), + CONVERT(HFP_CALL_STATE_WAITING, 0x05), + CONVERT(HFP_CALL_STATE_IDLE, 0x06) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallState))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallState[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallMode aIn, uint8_t& aOut) +{ + static const uint8_t sCallMode[] = { + CONVERT(HFP_CALL_MODE_VOICE, 0x00), + CONVERT(HFP_CALL_MODE_DATA, 0x01), + CONVERT(HFP_CALL_MODE_FAX, 0x02) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallMode))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallMode[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallMptyType aIn, uint8_t& aOut) +{ + static const uint8_t sCallMptyType[] = { + CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, 0x00), + CONVERT(HFP_CALL_MPTY_TYPE_MULTI, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallMptyType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallMptyType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeNetworkState aIn, uint8_t& aOut) +{ + static const uint8_t sNetworkState[] = { + CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, 0x00), + CONVERT(HFP_NETWORK_STATE_AVAILABLE, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sNetworkState))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNetworkState[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeServiceType aIn, uint8_t& aOut) +{ + static const uint8_t sServiceType[] = { + CONVERT(HFP_SERVICE_TYPE_HOME, 0x00), + CONVERT(HFP_SERVICE_TYPE_ROAMING, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sServiceType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sServiceType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeVolumeType aIn, uint8_t& aOut) +{ + static const uint8_t sVolumeType[] = { + CONVERT(HFP_VOLUME_TYPE_SPEAKER, 0x00), + CONVERT(HFP_VOLUME_TYPE_MICROPHONE, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVolumeType[aIn]; + return NS_OK; +} + +nsresult Convert(BluetoothPropertyType aIn, uint8_t& aOut) { static const uint8_t sPropertyType[] = { @@ -523,6 +781,69 @@ } nsresult +PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU) { nsresult rv = PackPDU( @@ -608,6 +929,12 @@ } nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); @@ -627,6 +954,50 @@ } nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeVoiceRecognitionState& aOut) +{ + return UnpackPDU( + aPDU, + UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut) { nsresult rv = UnpackPDU(aPDU, aOut.mType); @@ -769,4 +1140,64 @@ return UnpackPDU(aPDU, UnpackConversion(aOut)); } +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut) +{ + // We get a pointer to the first character in the PDU, a length + // of 1 ensures we consume the \0 byte. With 'str' pointing to + // the string in the PDU, we can copy the actual bytes. + + const char* str = reinterpret_cast(aPDU.Consume(1)); + if (NS_WARN_IF(!str)) { + return NS_ERROR_ILLEGAL_VALUE; // end of PDU + } + + const char* end = static_cast(memchr(str, '\0', aPDU.GetSize())); + if (NS_WARN_IF(!end)) { + return NS_ERROR_ILLEGAL_VALUE; // no string terminator + } + + ptrdiff_t len = end - str; + + const uint8_t* rest = aPDU.Consume(len); + if (NS_WARN_IF(!rest)) { + // We couldn't consume bytes that should have been there. + return NS_ERROR_ILLEGAL_VALUE; + } + + aOut.Rebind(str, len); + + return NS_OK; +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut) +{ + nsDependentCString cstring; + + nsresult rv = UnpackPDU(aPDU, cstring); + if (NS_FAILED(rv)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + aOut.mString->AssignASCII(cstring.get(), cstring.Length()); + + return NS_OK; +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut) +{ + nsDependentCString cstring; + + nsresult rv = UnpackPDU(aPDU, cstring); + if (NS_FAILED(rv)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + *aOut.mString = NS_ConvertUTF8toUTF16(cstring); + + return NS_OK; +} + END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h 2014-11-26 21:45:56.000000000 +0000 @@ -104,15 +104,42 @@ Convert(bool aIn, BluetoothScanMode& aOut); nsresult +Convert(int aIn, uint8_t& aOut); + +nsresult Convert(int aIn, int16_t& aOut); nsresult Convert(uint8_t aIn, bool& aOut); nsresult +Convert(uint8_t aIn, char& aOut); + +nsresult +Convert(uint8_t aIn, int& aOut); + +nsresult Convert(uint8_t aIn, BluetoothAclState& aOut); nsresult +Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeCallHoldType& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeConnectionState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeNRECState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVolumeType& aOut); + +nsresult Convert(uint8_t aIn, BluetoothBondState& aOut); nsresult @@ -158,6 +185,33 @@ Convert(const BluetoothAddress& aIn, nsAString& aOut); nsresult +Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallState aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallMode aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallMptyType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeNetworkState aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeServiceType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeVolumeType aIn, uint8_t& aOut); + +nsresult Convert(BluetoothPropertyType aIn, uint8_t& aOut); nsresult @@ -216,6 +270,33 @@ PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU); nsresult +PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU); nsresult @@ -302,6 +383,29 @@ return aPDU.Write(aIn.mData, aIn.mLength); } +/* |PackCString0| is a helper for packing 0-terminated C string, + * including the \0 character. Pass an instance of this structure + * as the first argument to |PackPDU| to pack a string. + */ +struct PackCString0 +{ + PackCString0(const nsCString& aString) + : mString(aString) + { } + + const nsCString& mString; +}; + +/* This implementation of |PackPDU| packs a 0-terminated C string. + */ +inline nsresult +PackPDU(const PackCString0& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackArray(reinterpret_cast(aIn.mString.get()), + aIn.mString.Length() + 1), aPDU); +} + template inline nsresult PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU) @@ -375,6 +479,41 @@ return PackPDU(aIn5, aPDU); } +template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7, BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn2, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn3, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn4, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn5, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn6, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn7, aPDU); +} + // // Unpacking // @@ -413,6 +552,9 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut); nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut); + +nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut); inline nsresult @@ -442,6 +584,25 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDeviceType& aOut); nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeVoiceRecognitionState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut); + +nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut); inline nsresult @@ -474,6 +635,9 @@ return aPDU.Read(aOut.mUuid, sizeof(aOut.mUuid)); } +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut); + /* |UnpackConversion| is a helper for convering unpacked values. Pass * an instance of this structure to |UnpackPDU| to read a value from * the PDU in the input type and convert it to the output type. @@ -565,6 +729,44 @@ return NS_OK; } +/* |UnpackCString0| is a helper for unpacking 0-terminated C string, + * including the \0 character. Pass an instance of this structure + * as the first argument to |UnpackPDU| to unpack a string. + */ +struct UnpackCString0 +{ + UnpackCString0(nsCString& aString) + : mString(&aString) + { } + + nsCString* mString; // non-null by construction +}; + +/* This implementation of |UnpackPDU| unpacks a 0-terminated C string. + */ +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut); + +/* |UnpackString0| is a helper for unpacking 0-terminated C string, + * including the \0 character. Pass an instance of this structure + * as the first argument to |UnpackPDU| to unpack a C string and convert + * it to wide-character encoding. + */ +struct UnpackString0 +{ + UnpackString0(nsString& aString) + : mString(&aString) + { } + + nsString* mString; // non-null by construction +}; + +/* This implementation of |UnpackPDU| unpacks a 0-terminated C string + * and converts it to wide-character encoding. + */ +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut); + // // Init operators // diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -5,6 +5,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BluetoothDaemonInterface.h" +#include "BluetoothDaemonHandsfreeInterface.h" #include "BluetoothDaemonHelpers.h" #include "BluetoothDaemonSetupInterface.h" #include "BluetoothDaemonSocketInterface.h" @@ -15,10 +16,6 @@ BEGIN_BLUETOOTH_NAMESPACE -template -struct interface_traits -{ }; - // // Protocol initialization and setup // @@ -1363,10 +1360,17 @@ , public BluetoothDaemonSetupModule , public BluetoothDaemonCoreModule , public BluetoothDaemonSocketModule + , public BluetoothDaemonHandsfreeModule { public: BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection); + nsresult RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE; + + nsresult UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE; + // Outgoing PDUs // @@ -1388,6 +1392,8 @@ BluetoothDaemonPDU& aPDU, void* aUserData); void HandleSocketSvc(const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleHandsfreeSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); BluetoothDaemonConnection* mConnection; nsTArray mUserDataQ; @@ -1401,6 +1407,20 @@ } nsresult +BluetoothDaemonProtocol::RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) +{ + return BluetoothDaemonSetupModule::RegisterModuleCmd(aId, aMode, aRes); +} + +nsresult +BluetoothDaemonProtocol::UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) +{ + return BluetoothDaemonSetupModule::UnregisterModuleCmd(aId, aRes); +} + +nsresult BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData) { MOZ_ASSERT(aPDU); @@ -1435,13 +1455,25 @@ } void +BluetoothDaemonProtocol::HandleHandsfreeSvc( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + BluetoothDaemonHandsfreeModule::HandleSvc(aHeader, aPDU, aUserData); +} + +void BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) { static void (BluetoothDaemonProtocol::* const HandleSvc[])( const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { INIT_ARRAY_AT(0x00, &BluetoothDaemonProtocol::HandleSetupSvc), INIT_ARRAY_AT(0x01, &BluetoothDaemonProtocol::HandleCoreSvc), - INIT_ARRAY_AT(0x02, &BluetoothDaemonProtocol::HandleSocketSvc) + INIT_ARRAY_AT(0x02, &BluetoothDaemonProtocol::HandleSocketSvc), + INIT_ARRAY_AT(0x03, nullptr), // HID host + INIT_ARRAY_AT(0x04, nullptr), // PAN + INIT_ARRAY_AT(BluetoothDaemonHandsfreeModule::SERVICE_ID, + &BluetoothDaemonProtocol::HandleHandsfreeSvc) }; BluetoothDaemonPDUHeader header; @@ -2009,7 +2041,13 @@ BluetoothHandsfreeInterface* BluetoothDaemonInterface::GetBluetoothHandsfreeInterface() { - return nullptr; + if (mHandsfreeInterface) { + return mHandsfreeInterface; + } + + mHandsfreeInterface = new BluetoothDaemonHandsfreeInterface(mProtocol); + + return mHandsfreeInterface; } BluetoothA2dpInterface* diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h 2014-11-26 21:45:56.000000000 +0000 @@ -12,6 +12,7 @@ BEGIN_BLUETOOTH_NAMESPACE class BluetoothDaemonChannel; +class BluetoothDaemonHandsfreeInterface; class BluetoothDaemonProtocol; class BluetoothDaemonSocketInterface; @@ -125,6 +126,7 @@ nsTArray > mResultHandlerQ; nsAutoPtr mSocketInterface; + nsAutoPtr mHandsfreeInterface; }; END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -64,126 +64,10 @@ static uint32_t sAdapterDiscoverableTimeout(0); /** - * Classes only used in this file - */ - -class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable -{ -public: - class SetAdapterPropertyResultHandler MOZ_FINAL - : public BluetoothResultHandler - { - public: - void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE - { - BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE"); - } - }; - - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - // Bluetooth just enabled, clear profile controllers and runnable arrays. - sControllerArray.Clear(); - sBondingRunnableArray.Clear(); - sGetDeviceRunnableArray.Clear(); - sSetPropertyRunnableArray.Clear(); - sUnbondingRunnableArray.Clear(); - - // Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should - // be connectable and non-discoverable. - NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE); - sBtInterface->SetAdapterProperty( - BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false), - new SetAdapterPropertyResultHandler()); - - // Try to fire event 'AdapterAdded' to fit the original behaviour when - // we used BlueZ as backend. - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE); - - bs->AdapterAddedReceived(); - bs->TryFiringAdapterAdded(); - - // Trigger BluetoothOppManager to listen - BluetoothOppManager* opp = BluetoothOppManager::Get(); - if (!opp || !opp->Listen()) { - BT_LOGR("Fail to start BluetoothOppManager listening"); - } - - return NS_OK; - } -}; - -/* |ProfileDeinitResultHandler| collect the results of all profile - * result handlers and calls |Proceed| after all results handlers - * have been run. - */ -class ProfileDeinitResultHandler MOZ_FINAL -: public BluetoothProfileResultHandler -{ -public: - ProfileDeinitResultHandler(unsigned char aNumProfiles) - : mNumProfiles(aNumProfiles) - { - MOZ_ASSERT(mNumProfiles); - } - - void Deinit() MOZ_OVERRIDE - { - if (!(--mNumProfiles)) { - Proceed(); - } - } - - void OnError(nsresult aResult) MOZ_OVERRIDE - { - if (!(--mNumProfiles)) { - Proceed(); - } - } - -private: - void Proceed() const - { - sBtInterface->Cleanup(nullptr); - } - - unsigned char mNumProfiles; -}; - -class CleanupTask MOZ_FINAL : public nsRunnable -{ -public: - NS_IMETHOD - Run() - { - static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = { - BluetoothHfpManager::DeinitHfpInterface, - BluetoothA2dpManager::DeinitA2dpInterface - }; - - MOZ_ASSERT(NS_IsMainThread()); - - // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF. - nsRefPtr res = - new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager)); - - for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) { - sDeinitManager[i](res); - } - - return NS_OK; - } -}; - -/** * Static callback functions */ -static void -ClassToIcon(uint32_t aClass, nsAString& aRetIcon) +void +BluetoothServiceBluedroid::ClassToIcon(uint32_t aClass, nsAString& aRetIcon) { switch ((aClass & 0x1f00) >> 8) { case 0x01: @@ -273,8 +157,9 @@ } } -static ControlPlayStatus -PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus) +ControlPlayStatus +BluetoothServiceBluedroid::PlayStatusStringToControlPlayStatus( + const nsAString& aPlayStatus) { ControlPlayStatus playStatus = ControlPlayStatus::PLAYSTATUS_UNKNOWN; if (aPlayStatus.EqualsLiteral("STOPPED")) { @@ -297,8 +182,8 @@ /** * Static functions */ -static bool -EnsureBluetoothHalLoad() +bool +BluetoothServiceBluedroid::EnsureBluetoothHalLoad() { sBtInterface = BluetoothInterface::GetInstance(); NS_ENSURE_TRUE(sBtInterface, false); @@ -306,7 +191,8 @@ return true; } -class EnableResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::EnableResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE @@ -315,10 +201,7 @@ BT_LOGR("BluetoothInterface::Enable failed: %d", aStatus); - nsRefPtr runnable = new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); } }; @@ -326,7 +209,7 @@ * result handlers and calls |Proceed| after all results handlers * have been run. */ -class ProfileInitResultHandler MOZ_FINAL +class BluetoothServiceBluedroid::ProfileInitResultHandler MOZ_FINAL : public BluetoothProfileResultHandler { public: @@ -359,7 +242,8 @@ unsigned char mNumProfiles; }; -class InitResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::InitResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: void Init() MOZ_OVERRIDE @@ -390,15 +274,12 @@ sBtInterface = nullptr; - nsRefPtr runnable = new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); } }; -static nsresult -StartGonkBluetooth() +nsresult +BluetoothServiceBluedroid::StartGonkBluetooth() { MOZ_ASSERT(NS_IsMainThread()); @@ -409,10 +290,7 @@ if (bs->IsEnabled()) { // Keep current enable status - nsRefPtr runnable = new BluetoothService::ToggleBtAck(true); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(true); return NS_OK; } @@ -422,7 +300,8 @@ return NS_OK; } -class DisableResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::DisableResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE @@ -431,15 +310,12 @@ BT_LOGR("BluetoothInterface::Disable failed: %d", aStatus); - nsRefPtr runnable = new BluetoothService::ToggleBtAck(true); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(true); } }; -static nsresult -StopGonkBluetooth() +nsresult +BluetoothServiceBluedroid::StopGonkBluetooth() { MOZ_ASSERT(NS_IsMainThread()); @@ -450,10 +326,7 @@ if (!bs->IsEnabled()) { // Keep current enable status - nsRefPtr runnable = new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); return NS_OK; } @@ -513,11 +386,7 @@ nsresult ret = StartGonkBluetooth(); if (NS_FAILED(ret)) { - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); BT_LOGR("Error"); } @@ -531,11 +400,7 @@ nsresult ret = StopGonkBluetooth(); if (NS_FAILED(ret)) { - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(true); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(true); BT_LOGR("Error"); } @@ -575,8 +440,8 @@ return NS_OK; } -class GetRemoteDevicePropertiesResultHandler MOZ_FINAL -: public BluetoothResultHandler +class BluetoothServiceBluedroid::GetRemoteDevicePropertiesResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: GetRemoteDevicePropertiesResultHandler(const nsAString& aDeviceAddress) @@ -677,7 +542,8 @@ return NS_OK; } -class StartDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::StartDiscoveryResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: StartDiscoveryResultHandler(BluetoothReplyRunnable* aRunnable) @@ -712,7 +578,8 @@ return NS_OK; } -class CancelDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::CancelDiscoveryResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: CancelDiscoveryResultHandler(BluetoothReplyRunnable* aRunnable) @@ -747,7 +614,8 @@ return NS_OK; } -class SetAdapterPropertyResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::SetAdapterPropertyResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: SetAdapterPropertyResultHandler(BluetoothReplyRunnable* aRunnable) @@ -796,7 +664,8 @@ return true; } -class CreateBondResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::CreateBondResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: CreateBondResultHandler(BluetoothReplyRunnable* aRunnable) @@ -830,7 +699,8 @@ return NS_OK; } -class RemoveBondResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::RemoveBondResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: RemoveBondResultHandler(BluetoothReplyRunnable* aRunnable) @@ -863,7 +733,8 @@ return NS_OK; } -class PinReplyResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::PinReplyResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: PinReplyResultHandler(BluetoothReplyRunnable* aRunnable) @@ -907,7 +778,8 @@ return true; } -class SspReplyResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::SspReplyResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: SspReplyResultHandler(BluetoothReplyRunnable* aRunnable) @@ -1230,6 +1102,54 @@ // Bluetooth notifications // +/* |ProfileDeinitResultHandler| collect the results of all profile + * result handlers and calls |Proceed| after all results handlers + * have been run. + */ +class BluetoothServiceBluedroid::ProfileDeinitResultHandler MOZ_FINAL +: public BluetoothProfileResultHandler +{ +public: + ProfileDeinitResultHandler(unsigned char aNumProfiles) + : mNumProfiles(aNumProfiles) + { + MOZ_ASSERT(mNumProfiles); + } + + void Deinit() MOZ_OVERRIDE + { + if (!(--mNumProfiles)) { + Proceed(); + } + } + + void OnError(nsresult aResult) MOZ_OVERRIDE + { + if (!(--mNumProfiles)) { + Proceed(); + } + } + +private: + void Proceed() const + { + sBtInterface->Cleanup(nullptr); + } + + unsigned char mNumProfiles; +}; + +class BluetoothServiceBluedroid::SetAdapterPropertyDiscoverableResultHandler + MOZ_FINAL + : public BluetoothResultHandler +{ +public: + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE"); + } +}; + void BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState) { @@ -1239,23 +1159,51 @@ bool isBtEnabled = (aState == true); - if (!isBtEnabled && - NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; - } + if (!isBtEnabled) { + static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = { + BluetoothHfpManager::DeinitHfpInterface, + BluetoothA2dpManager::DeinitA2dpInterface + }; - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(isBtEnabled); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; + // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF. + nsRefPtr res = + new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager)); + + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) { + sDeinitManager[i](res); + } } - if (isBtEnabled && - NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; + BluetoothService::AcknowledgeToggleBt(isBtEnabled); + + if (isBtEnabled) { + // Bluetooth just enabled, clear profile controllers and runnable arrays. + sControllerArray.Clear(); + sBondingRunnableArray.Clear(); + sGetDeviceRunnableArray.Clear(); + sSetPropertyRunnableArray.Clear(); + sUnbondingRunnableArray.Clear(); + + // Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should + // be connectable and non-discoverable. + NS_ENSURE_TRUE_VOID(sBtInterface); + sBtInterface->SetAdapterProperty( + BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false), + new SetAdapterPropertyDiscoverableResultHandler()); + + // Try to fire event 'AdapterAdded' to fit the original behaviour when + // we used BlueZ as backend. + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + + bs->AdapterAddedReceived(); + bs->TryFiringAdapterAdded(); + + // Trigger BluetoothOppManager to listen + BluetoothOppManager* opp = BluetoothOppManager::Get(); + if (!opp || !opp->Listen()) { + BT_LOGR("Fail to start BluetoothOppManager listening"); + } } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h 2014-11-26 21:45:56.000000000 +0000 @@ -16,6 +16,21 @@ class BluetoothServiceBluedroid : public BluetoothService , public BluetoothNotificationHandler { + class CancelDiscoveryResultHandler; + class CreateBondResultHandler; + class DisableResultHandler; + class EnableResultHandler; + class GetRemoteDevicePropertiesResultHandler; + class InitResultHandler; + class PinReplyResultHandler; + class ProfileDeinitResultHandler; + class ProfileInitResultHandler; + class RemoveBondResultHandler; + class SetAdapterPropertyDiscoverableResultHandler; + class SetAdapterPropertyResultHandler; + class SspReplyResultHandler; + class StartDiscoveryResultHandler; + public: BluetoothServiceBluedroid(); ~BluetoothServiceBluedroid(); @@ -196,6 +211,16 @@ uint8_t aLen) MOZ_OVERRIDE; virtual void LeTestModeNotification(BluetoothStatus aStatus, uint16_t aNumPackets) MOZ_OVERRIDE; + +protected: + static nsresult StartGonkBluetooth(); + static nsresult StopGonkBluetooth(); + static bool EnsureBluetoothHalLoad(); + + static void ClassToIcon(uint32_t aClass, nsAString& aRetIcon); + + static ControlPlayStatus PlayStatusStringToControlPlayStatus( + const nsAString& aPlayStatus); }; END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/BluetoothService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/BluetoothService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/BluetoothService.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/BluetoothService.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -146,41 +146,7 @@ NS_METHOD BluetoothService::ToggleBtAck::Run() { - MOZ_ASSERT(NS_IsMainThread()); - - // This is requested in Bug 836516. With settings this property, WLAN - // firmware could be aware of Bluetooth has been turned on/off, so that the - // mecahnism of handling coexistence of WIFI and Bluetooth could be started. - // - // In the future, we may have our own way instead of setting a system - // property to let firmware developers be able to sense that Bluetooth has - // been toggled. -#if defined(MOZ_WIDGET_GONK) - if (property_set(PROP_BLUETOOTH_ENABLED, mEnabled ? "true" : "false") != 0) { - BT_WARNING("Failed to set bluetooth enabled property"); - } -#endif - - NS_ENSURE_TRUE(sBluetoothService, NS_OK); - - if (sInShutdown) { - sBluetoothService = nullptr; - return NS_OK; - } - - // Update mEnabled of BluetoothService object since - // StartInternal/StopInternal have been already done. - sBluetoothService->SetEnabled(mEnabled); - sToggleInProgress = false; - - nsAutoString signalName; - signalName = mEnabled ? NS_LITERAL_STRING("Enabled") - : NS_LITERAL_STRING("Disabled"); - BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true); - sBluetoothService->DistributeSignal(signal); - - // Event 'AdapterAdded' has to be fired after firing 'Enabled' - sBluetoothService->TryFiringAdapterAdded(); + BluetoothService::AcknowledgeToggleBt(mEnabled); return NS_OK; } @@ -803,3 +769,53 @@ systemMessenger->BroadcastMessage(type, value, JS::UndefinedHandleValue); } + +void +BluetoothService::AcknowledgeToggleBt(bool aEnabled) +{ + MOZ_ASSERT(NS_IsMainThread()); + +#if defined(MOZ_WIDGET_GONK) + // This is requested in Bug 836516. With settings this property, WLAN + // firmware could be aware of Bluetooth has been turned on/off, so that + // the mechanism of handling coexistence of WIFI and Bluetooth could be + // started. + // + // In the future, we may have our own way instead of setting a system + // property to let firmware developers be able to sense that Bluetooth + // has been toggled. + if (property_set(PROP_BLUETOOTH_ENABLED, aEnabled ? "true" : "false") != 0) { + BT_WARNING("Failed to set bluetooth enabled property"); + } +#endif + + if (sInShutdown) { + sBluetoothService = nullptr; + return; + } + + NS_ENSURE_TRUE_VOID(sBluetoothService); + + sBluetoothService->CompleteToggleBt(aEnabled); +} + +void +BluetoothService::CompleteToggleBt(bool aEnabled) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Update |mEnabled| of |BluetoothService| object since + // |StartInternal| and |StopInternal| have been already + // done. + SetEnabled(aEnabled); + sToggleInProgress = false; + + nsAutoString signalName; + signalName = aEnabled ? NS_LITERAL_STRING("Enabled") + : NS_LITERAL_STRING("Disabled"); + BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true); + DistributeSignal(signal); + + // Event 'AdapterAdded' has to be fired after firing 'Enabled' + TryFiringAdapterAdded(); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/BluetoothService.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/BluetoothService.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/BluetoothService.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/BluetoothService.h 2014-11-26 21:45:56.000000000 +0000 @@ -313,6 +313,8 @@ bool IsToggling() const; + static void AcknowledgeToggleBt(bool aEnabled); + /** * Below 2 function/variable are used for ensuring event 'AdapterAdded' will * be fired after event 'Enabled'. @@ -393,6 +395,8 @@ static BluetoothService* Create(); + void CompleteToggleBt(bool aEnabled); + typedef nsClassHashtable BluetoothSignalObserverTable; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth/moz.build 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth/moz.build 2014-11-26 21:45:56.000000000 +0000 @@ -48,6 +48,7 @@ 'bluedroid/BluetoothA2dpHALInterface.cpp', 'bluedroid/BluetoothA2dpManager.cpp', 'bluedroid/BluetoothAvrcpHALInterface.cpp', + 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp', 'bluedroid/BluetoothDaemonHelpers.cpp', 'bluedroid/BluetoothDaemonInterface.cpp', 'bluedroid/BluetoothDaemonSetupInterface.cpp', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,756 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "BluetoothDaemonHelpers.h" +#include + +#define MAX_UUID_SIZE 16 + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Conversion +// + +nsresult +Convert(bool aIn, uint8_t& aOut) +{ + static const bool sValue[] = { + CONVERT(false, 0x00), + CONVERT(true, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) { + aOut = 0; + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sValue[aIn]; + return NS_OK; +} + +nsresult +Convert(bool aIn, BluetoothScanMode& aOut) +{ + static const BluetoothScanMode sScanMode[] = { + CONVERT(false, SCAN_MODE_CONNECTABLE), + CONVERT(true, SCAN_MODE_CONNECTABLE_DISCOVERABLE) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sScanMode))) { + aOut = SCAN_MODE_NONE; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sScanMode[aIn]; + return NS_OK; +} + +nsresult +Convert(int aIn, int16_t& aOut) +{ + if (NS_WARN_IF(aIn < std::numeric_limits::min()) || + NS_WARN_IF(aIn > std::numeric_limits::max())) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, bool& aOut) +{ + static const bool sBool[] = { + CONVERT(0x00, false), + CONVERT(0x01, true) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sBool))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sBool[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothAclState& aOut) +{ + static const BluetoothAclState sAclState[] = { + CONVERT(0x00, ACL_STATE_CONNECTED), + CONVERT(0x01, ACL_STATE_DISCONNECTED), + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAclState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAclState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothBondState& aOut) +{ + static const BluetoothBondState sBondState[] = { + CONVERT(0x00, BOND_STATE_NONE), + CONVERT(0x01, BOND_STATE_BONDING), + CONVERT(0x02, BOND_STATE_BONDED) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sBondState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sBondState[aIn]; + return NS_OK; +} + +nsresult +Convert(int32_t aIn, BluetoothTypeOfDevice& aOut) +{ + static const BluetoothTypeOfDevice sTypeOfDevice[] = { + CONVERT(0x00, static_cast(0)), // invalid, required by gcc + CONVERT(0x01, TYPE_OF_DEVICE_BREDR), + CONVERT(0x02, TYPE_OF_DEVICE_BLE), + CONVERT(0x03, TYPE_OF_DEVICE_DUAL) + }; + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(static_cast(aIn) >= MOZ_ARRAY_LENGTH(sTypeOfDevice))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sTypeOfDevice[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothPropertyType& aOut) +{ + static const BluetoothPropertyType sPropertyType[] = { + CONVERT(0x00, static_cast(0)), // invalid, required by gcc + CONVERT(0x01, PROPERTY_BDNAME), + CONVERT(0x02, PROPERTY_BDADDR), + CONVERT(0x03, PROPERTY_UUIDS), + CONVERT(0x04, PROPERTY_CLASS_OF_DEVICE), + CONVERT(0x05, PROPERTY_TYPE_OF_DEVICE), + CONVERT(0x06, PROPERTY_SERVICE_RECORD), + CONVERT(0x07, PROPERTY_ADAPTER_SCAN_MODE), + CONVERT(0x08, PROPERTY_ADAPTER_BONDED_DEVICES), + CONVERT(0x09, PROPERTY_ADAPTER_DISCOVERY_TIMEOUT), + CONVERT(0x0a, PROPERTY_REMOTE_FRIENDLY_NAME), + CONVERT(0x0b, PROPERTY_REMOTE_RSSI), + CONVERT(0x0c, PROPERTY_REMOTE_VERSION_INFO) + }; + if (aIn == 0xff) { + /* This case is handled separately to not populate + * |sPropertyType| with empty entries. */ + aOut = PROPERTY_REMOTE_DEVICE_TIMESTAMP; + return NS_OK; + } + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sPropertyType))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPropertyType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothSocketType aIn, uint8_t& aOut) +{ + static const uint8_t sSocketType[] = { + CONVERT(0, 0), // silences compiler warning + CONVERT(BluetoothSocketType::RFCOMM, 0x01), + CONVERT(BluetoothSocketType::SCO, 0x02), + CONVERT(BluetoothSocketType::L2CAP, 0x03) + // EL2CAP not supported + }; + if (NS_WARN_IF(aIn == BluetoothSocketType::EL2CAP) || + NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sSocketType)) || + NS_WARN_IF(!sSocketType[aIn])) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sSocketType[aIn]; + return NS_OK; +} + +nsresult +Convert(int32_t aIn, BluetoothScanMode& aOut) +{ + static const BluetoothScanMode sScanMode[] = { + CONVERT(0x00, SCAN_MODE_NONE), + CONVERT(0x01, SCAN_MODE_CONNECTABLE), + CONVERT(0x02, SCAN_MODE_CONNECTABLE_DISCOVERABLE) + }; + if (NS_WARN_IF(aIn < 0) || + NS_WARN_IF(static_cast(aIn) >= MOZ_ARRAY_LENGTH(sScanMode))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sScanMode[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothSspVariant& aOut) +{ + static const BluetoothSspVariant sSspVariant[] = { + CONVERT(0x00, SSP_VARIANT_PASSKEY_CONFIRMATION), + CONVERT(0x01, SSP_VARIANT_PASSKEY_ENTRY), + CONVERT(0x02, SSP_VARIANT_CONSENT), + CONVERT(0x03, SSP_VARIANT_PASSKEY_NOTIFICATION) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sSspVariant))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sSspVariant[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothStatus& aOut) +{ + static const BluetoothStatus sStatus[] = { + CONVERT(0x00, STATUS_SUCCESS), + CONVERT(0x01, STATUS_FAIL), + CONVERT(0x02, STATUS_NOT_READY), + CONVERT(0x03, STATUS_NOMEM), + CONVERT(0x04, STATUS_BUSY), + CONVERT(0x05, STATUS_DONE), + CONVERT(0x06, STATUS_UNSUPPORTED), + CONVERT(0x07, STATUS_PARM_INVALID), + CONVERT(0x08, STATUS_UNHANDLED), + CONVERT(0x09, STATUS_AUTH_FAILURE), + CONVERT(0x0a, STATUS_RMT_DEV_DOWN) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sStatus))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sStatus[aIn]; + return NS_OK; +} + +nsresult +Convert(uint32_t aIn, int& aOut) +{ + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult +Convert(size_t aIn, uint16_t& aOut) +{ + if (NS_WARN_IF(aIn >= (1ul << 16))) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, BluetoothAddress& aOut) +{ + NS_ConvertUTF16toUTF8 bdAddressUTF8(aIn); + const char* str = bdAddressUTF8.get(); + + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aOut.mAddr); ++i, ++str) { + aOut.mAddr[i] = + static_cast(strtoul(str, const_cast(&str), 16)); + } + + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, BluetoothPinCode& aOut) +{ + if (NS_WARN_IF(aIn.Length() > MOZ_ARRAY_LENGTH(aOut.mPinCode))) { + return NS_ERROR_ILLEGAL_VALUE; + } + + NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn); + const char* str = pinCodeUTF8.get(); + + nsAString::size_type i; + + // Fill pin into aOut + for (i = 0; i < aIn.Length(); ++i, ++str) { + aOut.mPinCode[i] = static_cast(*str); + } + + // Clear remaining bytes in aOut + size_t ntrailing = (MOZ_ARRAY_LENGTH(aOut.mPinCode) - aIn.Length()) * + sizeof(aOut.mPinCode[0]); + memset(aOut.mPinCode + aIn.Length(), 0, ntrailing); + + aOut.mLength = aIn.Length(); + + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, BluetoothPropertyType& aOut) +{ + if (aIn.EqualsLiteral("Name")) { + aOut = PROPERTY_BDNAME; + } else if (aIn.EqualsLiteral("Discoverable")) { + aOut = PROPERTY_ADAPTER_SCAN_MODE; + } else if (aIn.EqualsLiteral("DiscoverableTimeout")) { + aOut = PROPERTY_ADAPTER_DISCOVERY_TIMEOUT; + } else { + BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get()); + aOut = static_cast(0); // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, BluetoothServiceName& aOut) +{ + NS_ConvertUTF16toUTF8 serviceNameUTF8(aIn); + const char* str = serviceNameUTF8.get(); + size_t len = strlen(str); + + if (NS_WARN_IF(len > sizeof(aOut.mName))) { + return NS_ERROR_ILLEGAL_VALUE; + } + + memcpy(aOut.mName, str, len); + memset(aOut.mName + len, 0, sizeof(aOut.mName) - len); + + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, BluetoothSspVariant& aOut) +{ + if (aIn.EqualsLiteral("PasskeyConfirmation")) { + aOut = SSP_VARIANT_PASSKEY_CONFIRMATION; + } else if (aIn.EqualsLiteral("PasskeyEntry")) { + aOut = SSP_VARIANT_PASSKEY_ENTRY; + } else if (aIn.EqualsLiteral("Consent")) { + aOut = SSP_VARIANT_CONSENT; + } else if (aIn.EqualsLiteral("PasskeyNotification")) { + aOut = SSP_VARIANT_PASSKEY_NOTIFICATION; + } else { + BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get()); + aOut = SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + return NS_OK; +} + +nsresult +Convert(BluetoothAclState aIn, bool& aOut) +{ + static const bool sBool[] = { + CONVERT(ACL_STATE_CONNECTED, true), + CONVERT(ACL_STATE_DISCONNECTED, false) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sBool))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sBool[aIn]; + return NS_OK; +} + +nsresult +Convert(const BluetoothAddress& aIn, nsAString& aOut) +{ + char str[BLUETOOTH_ADDRESS_LENGTH + 1]; + + int res = snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", + static_cast(aIn.mAddr[0]), + static_cast(aIn.mAddr[1]), + static_cast(aIn.mAddr[2]), + static_cast(aIn.mAddr[3]), + static_cast(aIn.mAddr[4]), + static_cast(aIn.mAddr[5])); + if (NS_WARN_IF(res < 0)) { + return NS_ERROR_ILLEGAL_VALUE; + } else if (NS_WARN_IF((size_t)res >= sizeof(str))) { + return NS_ERROR_OUT_OF_MEMORY; /* string buffer too small */ + } + + aOut = NS_ConvertUTF8toUTF16(str); + + return NS_OK; +} + +nsresult +Convert(BluetoothPropertyType aIn, uint8_t& aOut) +{ + static const uint8_t sPropertyType[] = { + CONVERT(PROPERTY_UNKNOWN, 0x00), + CONVERT(PROPERTY_BDNAME, 0x01), + CONVERT(PROPERTY_BDADDR, 0x02), + CONVERT(PROPERTY_UUIDS, 0x03), + CONVERT(PROPERTY_CLASS_OF_DEVICE, 0x04), + CONVERT(PROPERTY_TYPE_OF_DEVICE, 0x05), + CONVERT(PROPERTY_SERVICE_RECORD, 0x06), + CONVERT(PROPERTY_ADAPTER_SCAN_MODE, 0x07), + CONVERT(PROPERTY_ADAPTER_BONDED_DEVICES, 0x08), + CONVERT(PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, 0x09), + CONVERT(PROPERTY_REMOTE_FRIENDLY_NAME, 0x0a), + CONVERT(PROPERTY_REMOTE_RSSI, 0x0b), + CONVERT(PROPERTY_REMOTE_VERSION_INFO, 0x0c), + CONVERT(PROPERTY_REMOTE_DEVICE_TIMESTAMP, 0xff) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sPropertyType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPropertyType[aIn]; + return NS_OK; +} + +nsresult +Convert(const BluetoothRemoteName& aIn, nsAString& aOut) +{ + // We construct an nsCString here because the string + // returned from the PDU is not 0-terminated. + aOut = NS_ConvertUTF8toUTF16( + nsCString(reinterpret_cast(aIn.mName), sizeof(aIn.mName))); + return NS_OK; +} + +nsresult +Convert(BluetoothScanMode aIn, int32_t& aOut) +{ + static const int32_t sScanMode[] = { + CONVERT(SCAN_MODE_NONE, 0x00), + CONVERT(SCAN_MODE_CONNECTABLE, 0x01), + CONVERT(SCAN_MODE_CONNECTABLE_DISCOVERABLE, 0x02) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sScanMode))) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sScanMode[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothSspVariant aIn, uint8_t& aOut) +{ + static const uint8_t sValue[] = { + CONVERT(SSP_VARIANT_PASSKEY_CONFIRMATION, 0x00), + CONVERT(SSP_VARIANT_PASSKEY_ENTRY, 0x01), + CONVERT(SSP_VARIANT_CONSENT, 0x02), + CONVERT(SSP_VARIANT_PASSKEY_NOTIFICATION, 0x03) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sValue[aIn]; + return NS_OK; +} + +/* |ConvertArray| is a helper for converting arrays. Pass an + * instance of this structure as the first argument to |Convert| + * to convert an array. The output type has to support the array + * subscript operator. + */ +template +struct ConvertArray +{ + ConvertArray(const T* aData, unsigned long aLength) + : mData(aData) + , mLength(aLength) + { } + + const T* mData; + unsigned long mLength; +}; + +/* This implementation of |Convert| converts the elements of an + * array one-by-one. The result data structures must have enough + * memory allocated. + */ +template +inline nsresult +Convert(const ConvertArray& aIn, Tout& aOut) +{ + for (unsigned long i = 0; i < aIn.mLength; ++i) { + nsresult rv = Convert(aIn.mData[i], aOut[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +// +// Packing +// + +nsresult +PackPDU(bool aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothAddress& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackArray(aIn.mAddr, sizeof(aIn.mAddr)), aPDU); +} + +nsresult +PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(aIn.mType, aIn.mLength, + PackArray(aIn.mValue.get(), aIn.mLength), aPDU); +} + +nsresult +PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(aIn.mService, aIn.mOpcode, aIn.mLength, aPDU); +} + +nsresult +PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU( + PackConversion(aIn.name()), aPDU); + if (NS_FAILED(rv)) { + return rv; + } + + if (aIn.value().type() == BluetoothValue::Tuint32_t) { + // Set discoverable timeout + rv = PackPDU(static_cast(sizeof(uint32_t)), + aIn.value().get_uint32_t(), aPDU); + } else if (aIn.value().type() == BluetoothValue::TnsString) { + // Set name + const nsCString value = + NS_ConvertUTF16toUTF8(aIn.value().get_nsString()); + + rv = PackPDU(PackConversion(value.Length()), + PackArray( + reinterpret_cast(value.get()), + value.Length()), + aPDU); + } else if (aIn.value().type() == BluetoothValue::Tbool) { + // Set scan mode + bool value = aIn.value().get_bool(); + + rv = PackPDU(static_cast(sizeof(int32_t)), + PackConversion(value), aPDU); + } else { + BT_LOGR("Invalid property value type"); + rv = NS_ERROR_ILLEGAL_VALUE; + } + return rv; +} + +nsresult +PackPDU(const BluetoothPinCode& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(aIn.mLength, + PackArray(aIn.mPinCode, sizeof(aIn.mPinCode)), + aPDU); +} + +nsresult +PackPDU(BluetoothPropertyType aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(BluetoothSspVariant aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), + aPDU); +} + +nsresult +PackPDU(BluetoothScanMode aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothServiceName& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackArray(aIn.mName, sizeof(aIn.mName)), aPDU); +} + +nsresult +PackPDU(BluetoothSocketType aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), aPDU); +} + +// +// Unpacking +// + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothBondState& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut) +{ + nsresult rv = UnpackPDU(aPDU, aOut.mType); + if (NS_FAILED(rv)) { + return rv; + } + uint16_t len; + rv = UnpackPDU(aPDU, len); + if (NS_FAILED(rv)) { + return rv; + } + + switch (aOut.mType) { + case PROPERTY_BDNAME: + /* fall through */ + case PROPERTY_REMOTE_FRIENDLY_NAME: { + const uint8_t* data = aPDU.Consume(len); + if (NS_WARN_IF(!data)) { + return NS_ERROR_ILLEGAL_VALUE; + } + // We construct an nsCString here because the string + // returned from the PDU is not 0-terminated. + aOut.mString = NS_ConvertUTF8toUTF16( + nsCString(reinterpret_cast(data), len)); + } + break; + case PROPERTY_BDADDR: + rv = UnpackPDU( + aPDU, UnpackConversion(aOut.mString)); + break; + case PROPERTY_UUIDS: { + size_t numUuids = len / MAX_UUID_SIZE; + aOut.mUuidArray.SetLength(numUuids); + rv = UnpackPDU(aPDU, aOut.mUuidArray); + } + break; + case PROPERTY_CLASS_OF_DEVICE: + /* fall through */ + case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + rv = UnpackPDU(aPDU, aOut.mUint32); + break; + case PROPERTY_TYPE_OF_DEVICE: + rv = UnpackPDU(aPDU, aOut.mTypeOfDevice); + break; + case PROPERTY_SERVICE_RECORD: + rv = UnpackPDU(aPDU, aOut.mServiceRecord); + break; + case PROPERTY_ADAPTER_SCAN_MODE: + rv = UnpackPDU(aPDU, aOut.mScanMode); + break; + case PROPERTY_ADAPTER_BONDED_DEVICES: { + /* unpack addresses */ + size_t numAddresses = len / BLUETOOTH_ADDRESS_BYTES; + nsAutoArrayPtr addresses; + UnpackArray addressArray(addresses, numAddresses); + rv = UnpackPDU(aPDU, addressArray); + if (NS_FAILED(rv)) { + return rv; + } + /* convert addresses to strings */ + aOut.mStringArray.SetLength(numAddresses); + ConvertArray convertArray(addressArray.mData, + addressArray.mLength); + rv = Convert(convertArray, aOut.mStringArray); + } + break; + case PROPERTY_REMOTE_RSSI: { + int8_t rssi; + rv = UnpackPDU(aPDU, rssi); + aOut.mInt32 = rssi; + } + break; + case PROPERTY_REMOTE_VERSION_INFO: + rv = UnpackPDU(aPDU, aOut.mRemoteInfo); + break; + case PROPERTY_REMOTE_DEVICE_TIMESTAMP: + /* nothing to do */ + break; + default: + break; + } + return rv; +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothPropertyType& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut) +{ + nsresult rv = UnpackPDU(aPDU, + UnpackConversion(aOut.mVerMajor)); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, UnpackConversion(aOut.mVerMinor)); + if (NS_FAILED(rv)) { + return rv; + } + return UnpackPDU(aPDU, UnpackConversion(aOut.mManufacturer)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothScanMode& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothServiceRecord& aOut) +{ + /* unpack UUID */ + nsresult rv = UnpackPDU(aPDU, aOut.mUuid); + if (NS_FAILED(rv)) { + return rv; + } + /* unpack channel */ + rv = UnpackPDU(aPDU, aOut.mChannel); + if (NS_FAILED(rv)) { + return rv; + } + /* unpack name */ + return aPDU.Read(aOut.mName, sizeof(aOut.mName)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothSspVariant& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,706 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothdaemonhelpers_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemonhelpers_h__ + +#include "BluetoothCommon.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/dom/bluetooth/BluetoothTypes.h" +#include "mozilla/ipc/BluetoothDaemonConnection.h" +#include "nsThreadUtils.h" + +using namespace mozilla::ipc; + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Helper structures +// + +enum BluetoothAclState { + ACL_STATE_CONNECTED, + ACL_STATE_DISCONNECTED +}; + +struct BluetoothAddress { + uint8_t mAddr[6]; +}; + +struct BluetoothConfigurationParameter { + uint8_t mType; + uint16_t mLength; + nsAutoArrayPtr mValue; +}; + +struct BluetoothDaemonPDUHeader { + BluetoothDaemonPDUHeader() + : mService(0x00) + , mOpcode(0x00) + , mLength(0x00) + { } + + BluetoothDaemonPDUHeader(uint8_t aService, uint8_t aOpcode, uint8_t aLength) + : mService(aService) + , mOpcode(aOpcode) + , mLength(aLength) + { } + + uint8_t mService; + uint8_t mOpcode; + uint16_t mLength; +}; + +struct BluetoothPinCode { + uint8_t mPinCode[16]; + uint8_t mLength; +}; + +struct BluetoothRemoteName { + uint8_t mName[249]; +}; + +struct BluetoothServiceName { + uint8_t mName[256]; +}; + +// +// Conversion +// +// PDUs can only store primitive data types, such as integers or +// strings. Gecko often uses more complex data types, such as +// enumerators or structures. Conversion functions convert between +// primitive data and internal Gecko's data types during a PDU's +// packing and unpacking. +// + +nsresult +Convert(bool aIn, uint8_t& aOut); + +nsresult +Convert(bool aIn, BluetoothScanMode& aOut); + +nsresult +Convert(int aIn, int16_t& aOut); + +nsresult +Convert(uint8_t aIn, bool& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothAclState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothBondState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothTypeOfDevice& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothPropertyType& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothScanMode& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothSspVariant& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothStatus& aOut); + +nsresult +Convert(uint32_t aIn, int& aOut); + +nsresult +Convert(size_t aIn, uint16_t& aOut); + +nsresult +Convert(const nsAString& aIn, BluetoothAddress& aOut); + +nsresult +Convert(const nsAString& aIn, BluetoothPinCode& aOut); + +nsresult +Convert(const nsAString& aIn, BluetoothPropertyType& aOut); + +nsresult +Convert(const nsAString& aIn, BluetoothServiceName& aOut); + +nsresult +Convert(const nsAString& aIn, BluetoothSspVariant& aOut); + +nsresult +Convert(BluetoothAclState aIn, bool& aOut); + +nsresult +Convert(const BluetoothAddress& aIn, nsAString& aOut); + +nsresult +Convert(BluetoothPropertyType aIn, uint8_t& aOut); + +nsresult +Convert(const BluetoothRemoteName& aIn, nsAString& aOut); + +nsresult +Convert(BluetoothScanMode aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothSocketType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothSspVariant aIn, uint8_t& aOut); + +// +// Packing +// + +nsresult +PackPDU(bool aIn, BluetoothDaemonPDU& aPDU); + +inline nsresult +PackPDU(uint8_t aIn, BluetoothDaemonPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +inline nsresult +PackPDU(uint16_t aIn, BluetoothDaemonPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +inline nsresult +PackPDU(int32_t aIn, BluetoothDaemonPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +inline nsresult +PackPDU(uint32_t aIn, BluetoothDaemonPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +nsresult +PackPDU(const BluetoothAddress& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothPinCode& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(BluetoothPropertyType aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothServiceName& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(BluetoothSocketType aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(BluetoothSspVariant aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(BluetoothScanMode aIn, BluetoothDaemonPDU& aPDU); + +/* |PackConversion| is a helper for packing converted values. Pass + * an instance of this structure to |PackPDU| to convert a value from + * the input type to the output type and and write it to the PDU. + */ +template +struct PackConversion { + PackConversion(const Tin& aIn) + : mIn(aIn) + { } + + const Tin& mIn; +}; + +template +inline nsresult +PackPDU(const PackConversion& aIn, BluetoothDaemonPDU& aPDU) +{ + Tout out; + + nsresult rv = Convert(aIn.mIn, out); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(out, aPDU); +} + +/* |PackArray| is a helper for packing arrays. Pass an instance + * of this structure as the first argument to |PackPDU| to pack + * an array. The array's maximum default length is 255 elements. + */ +template +struct PackArray +{ + PackArray(const T* aData, size_t aLength) + : mData(aData) + , mLength(aLength) + { } + + const T* mData; + size_t mLength; +}; + +/* This implementation of |PackPDU| packs the length of an array + * and the elements of the array one-by-one. + */ +template +inline nsresult +PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) +{ + for (size_t i = 0; i < aIn.mLength; ++i) { + nsresult rv = PackPDU(aIn.mData[i], aPDU); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +template<> +inline nsresult +PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) +{ + /* Write raw bytes in one pass */ + return aPDU.Write(aIn.mData, aIn.mLength); +} + +template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn2, aPDU); +} + +template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, + BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn2, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn3, aPDU); +} + +template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4, + BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn2, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn3, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn4, aPDU); +} + +template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, + BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn2, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn3, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn4, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn5, aPDU); +} + +// +// Unpacking +// + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, int8_t& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, uint8_t& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, uint16_t& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, int32_t& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, uint32_t& aOut) +{ + return aPDU.Read(aOut); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut); + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAddress& aOut) +{ + return aPDU.Read(aOut.mAddr, sizeof(aOut.mAddr)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothBondState& aOut); + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDaemonPDUHeader& aOut) +{ + nsresult rv = UnpackPDU(aPDU, aOut.mService); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, aOut.mOpcode); + if (NS_FAILED(rv)) { + return rv; + } + return UnpackPDU(aPDU, aOut.mLength); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut); + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteName& aOut) +{ + return aPDU.Read(aOut.mName, sizeof(aOut.mName)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothPropertyType& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothScanMode& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothServiceRecord& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothSspVariant& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut); + +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothUuid& aOut) +{ + return aPDU.Read(aOut.mUuid, sizeof(aOut.mUuid)); +} + +/* |UnpackConversion| is a helper for convering unpacked values. Pass + * an instance of this structure to |UnpackPDU| to read a value from + * the PDU in the input type and convert it to the output type. + */ +template +struct UnpackConversion { + UnpackConversion(Tout& aOut) + : mOut(aOut) + { } + + Tout& mOut; +}; + +template +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackConversion& aOut) +{ + Tin in; + nsresult rv = UnpackPDU(aPDU, in); + if (NS_FAILED(rv)) { + return rv; + } + return Convert(in, aOut.mOut); +} + +/* |UnpackArray| is a helper for unpacking arrays. Pass an instance + * of this structure as the second argument to |UnpackPDU| to unpack + * an array. + */ +template +struct UnpackArray +{ + UnpackArray(T* aData, size_t aLength) + : mData(aData) + , mLength(aLength) + { } + + UnpackArray(nsAutoArrayPtr& aData, size_t aLength) + : mData(nullptr) + , mLength(aLength) + { + aData = new T[mLength]; + mData = aData.get(); + } + + UnpackArray(nsAutoArrayPtr& aData, size_t aSize, size_t aElemSize) + : mData(nullptr) + , mLength(aSize / aElemSize) + { + aData = new T[mLength]; + mData = aData.get(); + } + + T* mData; + size_t mLength; +}; + +template +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackArray& aOut) +{ + for (size_t i = 0; i < aOut.mLength; ++i) { + nsresult rv = UnpackPDU(aPDU, aOut.mData[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +template<> +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackArray& aOut) +{ + /* Read raw bytes in one pass */ + return aPDU.Read(aOut.mData, aOut.mLength); +} + +template +inline nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, nsTArray& aOut) +{ + for (typename nsTArray::size_type i = 0; i < aOut.Length(); ++i) { + nsresult rv = UnpackPDU(aPDU, aOut[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +// +// Init operators +// + +// |PDUInitOP| provides functionality for init operators that unpack PDUs. +class PDUInitOp +{ +protected: + PDUInitOp(BluetoothDaemonPDU& aPDU) + : mPDU(&aPDU) + { } + + BluetoothDaemonPDU& GetPDU() const + { + return *mPDU; // cannot be nullptr + } + + void WarnAboutTrailingData() const + { + size_t size = mPDU->GetSize(); + + if (MOZ_LIKELY(!size)) { + return; + } + + uint8_t service, opcode; + uint16_t payloadSize; + mPDU->GetHeader(service, opcode, payloadSize); + + BT_LOGR("Unpacked PDU of type (%x,%x) still contains %zu Bytes of data.", + service, opcode, size); + } + +private: + BluetoothDaemonPDU* mPDU; // Hold pointer to allow for constant instances +}; + +// |UnpackPDUInitOp| is a general-purpose init operator for all variants +// of |BluetoothResultRunnable| and |BluetoothNotificationRunnable|. The +// call operators of |UnpackPDUInitOp| unpack a PDU into the supplied +// arguments. +class UnpackPDUInitOp MOZ_FINAL : private PDUInitOp +{ +public: + UnpackPDUInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult operator () () const + { + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1) const + { + nsresult rv = UnpackPDU(GetPDU(), aArg1); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1, T2& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, + T5& aArg5) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,2134 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "BluetoothDaemonInterface.h" +#include "BluetoothDaemonHelpers.h" +#include "BluetoothDaemonSetupInterface.h" +#include "BluetoothDaemonSocketInterface.h" +#include "BluetoothInterfaceHelpers.h" +#include "mozilla/unused.h" + +using namespace mozilla::ipc; + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Protocol initialization and setup +// + +class BluetoothDaemonSetupModule +{ +public: + enum { + SERVICE_ID = 0x00 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_REGISTER_MODULE = 0x01, + OPCODE_UNREGISTER_MODULE = 0x02, + OPCODE_CONFIGURATION = 0x03 + }; + + virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + + // Commands + // + + nsresult RegisterModuleCmd(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_REGISTER_MODULE, 0)); + + nsresult rv = PackPDU(aId, aMode, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult UnregisterModuleCmd(uint8_t aId, + BluetoothSetupResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_UNREGISTER_MODULE, 0)); + + nsresult rv = PackPDU(aId, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult ConfigurationCmd(const BluetoothConfigurationParameter* aParam, + uint8_t aLen, BluetoothSetupResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONFIGURATION, 0)); + + nsresult rv = PackPDU( + aLen, PackArray(aParam, aLen), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + +protected: + + // Called to handle PDUs with Service field equal to 0x00, which + // contains internal operations for setup and configuration. + void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) + { + static void (BluetoothDaemonSetupModule::* const HandleRsp[])( + const BluetoothDaemonPDUHeader&, + BluetoothDaemonPDU&, + BluetoothSetupResultHandler*) = { + INIT_ARRAY_AT(OPCODE_ERROR, + &BluetoothDaemonSetupModule::ErrorRsp), + INIT_ARRAY_AT(OPCODE_REGISTER_MODULE, + &BluetoothDaemonSetupModule::RegisterModuleRsp), + INIT_ARRAY_AT(OPCODE_UNREGISTER_MODULE, + &BluetoothDaemonSetupModule::UnregisterModuleRsp), + INIT_ARRAY_AT(OPCODE_CONFIGURATION, + &BluetoothDaemonSetupModule::ConfigurationRsp) + }; + + if (NS_WARN_IF(aHeader.mOpcode >= MOZ_ARRAY_LENGTH(HandleRsp)) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + + if (!res) { + return; // Return early if no result handler has been set + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); + } + + nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothSetupResultHandler* aRes) + { + aRes->AddRef(); // Keep reference for response + return Send(aPDU, static_cast(aRes)); + } + +private: + + // Responses + // + + typedef + BluetoothResultRunnable0 + ResultRunnable; + + typedef + BluetoothResultRunnable1 + ErrorRunnable; + + void + ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSetupResultHandler* aRes) + { + ErrorRunnable::Dispatch( + aRes, &BluetoothSetupResultHandler::OnError, UnpackPDUInitOp(aPDU)); + } + + void + RegisterModuleRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSetupResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothSetupResultHandler::RegisterModule, + UnpackPDUInitOp(aPDU)); + } + + void + UnregisterModuleRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSetupResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothSetupResultHandler::UnregisterModule, + UnpackPDUInitOp(aPDU)); + } + + void + ConfigurationRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSetupResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothSetupResultHandler::Configuration, + UnpackPDUInitOp(aPDU)); + } +}; + +// +// Core module +// + +static BluetoothNotificationHandler* sNotificationHandler; + +class BluetoothDaemonCoreModule +{ +public: + enum { + SERVICE_ID = 0x01 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_ENABLE = 0x01, + OPCODE_DISABLE = 0x02, + OPCODE_GET_ADAPTER_PROPERTIES = 0x03, + OPCODE_GET_ADAPTER_PROPERTY = 0x04, + OPCODE_SET_ADAPTER_PROPERTY = 0x05, + OPCODE_GET_REMOTE_DEVICE_PROPERTIES = 0x06, + OPCODE_GET_REMOTE_DEVICE_PROPERTY = 0x07, + OPCODE_SET_REMOTE_DEVICE_PROPERTY = 0x08, + OPCODE_GET_REMOTE_SERVICE_RECORD = 0x09, + OPCODE_GET_REMOTE_SERVICES = 0x0a, + OPCODE_START_DISCOVERY = 0x0b, + OPCODE_CANCEL_DISCOVERY = 0x0c, + OPCODE_CREATE_BOND = 0x0d, + OPCODE_REMOVE_BOND = 0x0e, + OPCODE_CANCEL_BOND = 0x0f, + OPCODE_PIN_REPLY = 0x10, + OPCODE_SSP_REPLY = 0x11, + OPCODE_DUT_MODE_CONFIGURE = 0x12, + OPCODE_DUT_MODE_SEND = 0x13, + OPCODE_LE_TEST_MODE = 0x14, + OPCODE_ADAPTER_STATE_CHANGED_NTF = 0x81, + OPCODE_ADAPTER_PROPERTIES_CHANGED_NTF = 0x82, + OPCODE_REMOTE_DEVICE_PROPERTIES_NTF = 0x83, + OPCODE_DEVICE_FOUND_NTF = 0x84, + OPCODE_DISCOVERY_STATE_CHANGED_NTF = 0x85, + OPCODE_PIN_REQUEST_NTF = 0x86, + OPCODE_SSP_REQUEST_NTF = 0x87, + OPCODE_BOND_STATE_CHANGED_NTF = 0x88, + OPCODE_ACL_STATE_CHANGED_NTF = 0x89, + OPCODE_DUT_MODE_RECEIVE_NTF = 0x8a, + OPCODE_LE_TEST_MODE_NTF = 0x8b + }; + + virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + + nsresult EnableCmd(BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_ENABLE, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult DisableCmd(BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISABLE, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult GetAdapterPropertiesCmd(BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTIES, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult GetAdapterPropertyCmd(const nsAString& aName, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTY, 0)); + + nsresult rv = PackPDU( + PackConversion(aName), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult SetAdapterPropertyCmd(const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_ADAPTER_PROPERTY, 0)); + + nsresult rv = PackPDU(aProperty, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult GetRemoteDevicePropertiesCmd(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTIES, + 0)); + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult GetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr, + const nsAString& aName, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTY, + 0)); + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), + PackConversion(aName), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult SetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr, + const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_REMOTE_DEVICE_PROPERTY, + 0)); + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), + aProperty, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult GetRemoteServiceRecordCmd(const nsAString& aRemoteAddr, + const uint8_t aUuid[16], + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_REMOTE_SERVICE_RECORD, + 0)); + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), + PackArray(aUuid, 16), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult GetRemoteServicesCmd(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_REMOTE_SERVICES, 0)); + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult StartDiscoveryCmd(BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_START_DISCOVERY, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult CancelDiscoveryCmd(BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CANCEL_DISCOVERY, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult CreateBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CREATE_BOND, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult RemoveBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_REMOVE_BOND, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult CancelBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CANCEL_BOND, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult PinReplyCmd(const nsAString& aBdAddr, bool aAccept, + const nsAString& aPinCode, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_PIN_REPLY, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), + aAccept, + PackConversion(aPinCode), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult SspReplyCmd(const nsAString& aBdAddr, const nsAString& aVariant, + bool aAccept, uint32_t aPasskey, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SSP_REPLY, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), + PackConversion(aVariant), + aAccept, aPasskey, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult DutModeConfigureCmd(bool aEnable, BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DUT_MODE_CONFIGURE, 0)); + + nsresult rv = PackPDU(aEnable, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult DutModeSendCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DUT_MODE_SEND, 0)); + + nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), + *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + + nsresult LeTestModeCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes) + { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LE_TEST_MODE, 0)); + + nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), + *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; + } + +protected: + + void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) + { + static void (BluetoothDaemonCoreModule::* const HandleOp[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + INIT_ARRAY_AT(0, &BluetoothDaemonCoreModule::HandleRsp), + INIT_ARRAY_AT(1, &BluetoothDaemonCoreModule::HandleNtf), + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + /* test notification bit; negating twice maps to 0 or 1 */ + unsigned int isNtf = !!(aHeader.mOpcode & 0x80); + + (this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData); + } + + nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothResultHandler* aRes) + { + aRes->AddRef(); // Keep reference for response + return Send(aPDU, static_cast(aRes)); + } + +private: + + // Responses + // + + typedef BluetoothResultRunnable0 + ResultRunnable; + + typedef BluetoothResultRunnable1 + ErrorRunnable; + + void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ErrorRunnable::Dispatch( + aRes, &BluetoothResultHandler::OnError, UnpackPDUInitOp(aPDU)); + } + + void EnableRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::Enable, UnpackPDUInitOp(aPDU)); + } + + void DisableRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::Disable, UnpackPDUInitOp(aPDU)); + } + + void GetAdapterPropertiesRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetAdapterProperties, + UnpackPDUInitOp(aPDU)); + } + + void GetAdapterPropertyRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetAdapterProperty, + UnpackPDUInitOp(aPDU)); + } + + void SetAdapterPropertyRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::SetAdapterProperty, + UnpackPDUInitOp(aPDU)); + } + + void GetRemoteDevicePropertiesRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteDeviceProperties, + UnpackPDUInitOp(aPDU)); + } + + void + GetRemoteDevicePropertyRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteDeviceProperty, + UnpackPDUInitOp(aPDU)); + } + + void SetRemoteDevicePropertyRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::SetRemoteDeviceProperty, + UnpackPDUInitOp(aPDU)); + } + + void GetRemoteServiceRecordRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteServiceRecord, + UnpackPDUInitOp(aPDU)); + } + + void GetRemoteServicesRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteServices, + UnpackPDUInitOp(aPDU)); + } + + void StartDiscoveryRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::StartDiscovery, + UnpackPDUInitOp(aPDU)); + } + + void CancelDiscoveryRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::CancelDiscovery, + UnpackPDUInitOp(aPDU)); + } + + void CreateBondRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::CreateBond, + UnpackPDUInitOp(aPDU)); + } + + void RemoveBondRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::RemoveBond, + UnpackPDUInitOp(aPDU)); + } + + void CancelBondRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::CancelBond, + UnpackPDUInitOp(aPDU)); + } + + void PinReplyRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::PinReply, + UnpackPDUInitOp(aPDU)); + } + + void SspReplyRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::SspReply, + UnpackPDUInitOp(aPDU)); + } + + void DutModeConfigureRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::DutModeConfigure, + UnpackPDUInitOp(aPDU)); + } + + void DutModeSendRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::DutModeSend, + UnpackPDUInitOp(aPDU)); + } + + void LeTestModeRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothResultHandler* aRes) + { + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::LeTestMode, + UnpackPDUInitOp(aPDU)); + } + + void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) + { + static void (BluetoothDaemonCoreModule::* const HandleRsp[])( + const BluetoothDaemonPDUHeader&, + BluetoothDaemonPDU&, + BluetoothResultHandler*) = { + INIT_ARRAY_AT(OPCODE_ERROR, + &BluetoothDaemonCoreModule::ErrorRsp), + INIT_ARRAY_AT(OPCODE_ENABLE, + &BluetoothDaemonCoreModule::EnableRsp), + INIT_ARRAY_AT(OPCODE_DISABLE, + &BluetoothDaemonCoreModule::DisableRsp), + INIT_ARRAY_AT(OPCODE_GET_ADAPTER_PROPERTIES, + &BluetoothDaemonCoreModule::GetAdapterPropertiesRsp), + INIT_ARRAY_AT(OPCODE_GET_ADAPTER_PROPERTY, + &BluetoothDaemonCoreModule::GetAdapterPropertyRsp), + INIT_ARRAY_AT(OPCODE_SET_ADAPTER_PROPERTY, + &BluetoothDaemonCoreModule::SetAdapterPropertyRsp), + INIT_ARRAY_AT(OPCODE_GET_REMOTE_DEVICE_PROPERTIES, + &BluetoothDaemonCoreModule::GetRemoteDevicePropertiesRsp), + INIT_ARRAY_AT(OPCODE_GET_REMOTE_DEVICE_PROPERTY, + &BluetoothDaemonCoreModule::GetRemoteDevicePropertyRsp), + INIT_ARRAY_AT(OPCODE_SET_REMOTE_DEVICE_PROPERTY, + &BluetoothDaemonCoreModule::SetRemoteDevicePropertyRsp), + INIT_ARRAY_AT(OPCODE_GET_REMOTE_SERVICE_RECORD, + &BluetoothDaemonCoreModule::GetRemoteServiceRecordRsp), + INIT_ARRAY_AT(OPCODE_GET_REMOTE_SERVICES, + &BluetoothDaemonCoreModule::GetRemoteServicesRsp), + INIT_ARRAY_AT(OPCODE_START_DISCOVERY, + &BluetoothDaemonCoreModule::StartDiscoveryRsp), + INIT_ARRAY_AT(OPCODE_CANCEL_DISCOVERY, + &BluetoothDaemonCoreModule::CancelDiscoveryRsp), + INIT_ARRAY_AT(OPCODE_CREATE_BOND, + &BluetoothDaemonCoreModule::CreateBondRsp), + INIT_ARRAY_AT(OPCODE_REMOVE_BOND, + &BluetoothDaemonCoreModule::RemoveBondRsp), + INIT_ARRAY_AT(OPCODE_CANCEL_BOND, + &BluetoothDaemonCoreModule::CancelBondRsp), + INIT_ARRAY_AT(OPCODE_PIN_REPLY, + &BluetoothDaemonCoreModule::PinReplyRsp), + INIT_ARRAY_AT(OPCODE_SSP_REPLY, + &BluetoothDaemonCoreModule::SspReplyRsp), + INIT_ARRAY_AT(OPCODE_DUT_MODE_CONFIGURE, + &BluetoothDaemonCoreModule::DutModeConfigureRsp), + INIT_ARRAY_AT(OPCODE_DUT_MODE_SEND, + &BluetoothDaemonCoreModule::DutModeSendRsp), + INIT_ARRAY_AT(OPCODE_LE_TEST_MODE, + &BluetoothDaemonCoreModule::LeTestModeRsp), + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + + if (!res) { + return; // Return early if no result handler has been set for response + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); + } + + // Notifications + // + + class NotificationHandlerWrapper + { + public: + typedef BluetoothNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } + }; + + typedef BluetoothNotificationRunnable1 + AdapterStateChangedNotification; + + typedef BluetoothNotificationRunnable3, + BluetoothStatus, int, + const BluetoothProperty*> + AdapterPropertiesNotification; + + typedef BluetoothNotificationRunnable4, + BluetoothStatus, const nsAString&, + int, const BluetoothProperty*> + RemoteDevicePropertiesNotification; + + typedef BluetoothNotificationRunnable2, + int, const BluetoothProperty*> + DeviceFoundNotification; + + typedef BluetoothNotificationRunnable1 + DiscoveryStateChangedNotification; + + typedef BluetoothNotificationRunnable3 + PinRequestNotification; + + typedef BluetoothNotificationRunnable5 + SspRequestNotification; + + typedef BluetoothNotificationRunnable3 + BondStateChangedNotification; + + typedef BluetoothNotificationRunnable3 + AclStateChangedNotification; + + typedef BluetoothNotificationRunnable3, + uint8_t, uint16_t, const uint8_t*> + DutModeRecvNotification; + + typedef BluetoothNotificationRunnable2 + LeTestModeNotification; + + void AdapterStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + AdapterStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::AdapterStateChangedNotification, + UnpackPDUInitOp(aPDU)); + } + + // Init operator class for AdapterPropertiesNotification + class AdapterPropertiesInitOp MOZ_FINAL : private PDUInitOp + { + public: + AdapterPropertiesInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, int& aArg2, + nsAutoArrayPtr& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read number of properties */ + uint8_t numProperties; + rv = UnpackPDU(pdu, numProperties); + if (NS_FAILED(rv)) { + return rv; + } + aArg2 = numProperties; + + /* Read properties array */ + UnpackArray properties(aArg3, aArg2); + rv = UnpackPDU(pdu, properties); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void AdapterPropertiesNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + AdapterPropertiesNotification::Dispatch( + &BluetoothNotificationHandler::AdapterPropertiesNotification, + AdapterPropertiesInitOp(aPDU)); + } + + // Init operator class for RemoteDevicePropertiesNotification + class RemoteDevicePropertiesInitOp MOZ_FINAL : private PDUInitOp + { + public: + RemoteDevicePropertiesInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, nsString& aArg2, int& aArg3, + nsAutoArrayPtr& aArg4) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read number of properties */ + uint8_t numProperties; + rv = UnpackPDU(pdu, numProperties); + if (NS_FAILED(rv)) { + return rv; + } + aArg3 = numProperties; + + /* Read properties array */ + UnpackArray properties(aArg4, aArg3); + rv = UnpackPDU(pdu, properties); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void RemoteDevicePropertiesNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + RemoteDevicePropertiesNotification::Dispatch( + &BluetoothNotificationHandler::RemoteDevicePropertiesNotification, + RemoteDevicePropertiesInitOp(aPDU)); + } + + // Init operator class for DeviceFoundNotification + class DeviceFoundInitOp MOZ_FINAL : private PDUInitOp + { + public: + DeviceFoundInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, nsAutoArrayPtr& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read number of properties */ + uint8_t numProperties; + nsresult rv = UnpackPDU(pdu, numProperties); + if (NS_FAILED(rv)) { + return rv; + } + aArg1 = numProperties; + + /* Read properties array */ + UnpackArray properties(aArg2, aArg1); + rv = UnpackPDU(pdu, properties); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void DeviceFoundNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + DeviceFoundNotification::Dispatch( + &BluetoothNotificationHandler::DeviceFoundNotification, + DeviceFoundInitOp(aPDU)); + } + + void DiscoveryStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + DiscoveryStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::DiscoveryStateChangedNotification, + UnpackPDUInitOp(aPDU)); + } + + // Init operator class for PinRequestNotification + class PinRequestInitOp MOZ_FINAL : private PDUInitOp + { + public: + PinRequestInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read remote address */ + nsresult rv = UnpackPDU( + pdu, UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote name */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read CoD */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void PinRequestNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + PinRequestNotification::Dispatch( + &BluetoothNotificationHandler::PinRequestNotification, + PinRequestInitOp(aPDU)); + } + + // Init operator class for SspRequestNotification + class SspRequestInitOp MOZ_FINAL : private PDUInitOp + { + public: + SspRequestInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3, + BluetoothSspVariant aArg4, uint32_t& aArg5) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read remote address */ + nsresult rv = UnpackPDU( + pdu, UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote name */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read CoD */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read pairing variant */ + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read passkey */ + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void SspRequestNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + SspRequestNotification::Dispatch( + &BluetoothNotificationHandler::SspRequestNotification, + SspRequestInitOp(aPDU)); + } + + // Init operator class for BondStateChangedNotification + class BondStateChangedInitOp MOZ_FINAL : private PDUInitOp + { + public: + BondStateChangedInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, nsString& aArg2, + BluetoothBondState& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read bond state */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void BondStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + BondStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::BondStateChangedNotification, + BondStateChangedInitOp(aPDU)); + } + + // Init operator class for AclStateChangedNotification + class AclStateChangedInitOp MOZ_FINAL : private PDUInitOp + { + public: + AclStateChangedInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, nsString& aArg2, bool& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read ACL state */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void AclStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + AclStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::AclStateChangedNotification, + AclStateChangedInitOp(aPDU)); + } + + // Init operator class for DutModeRecvNotification + class DutModeRecvInitOp MOZ_FINAL : private PDUInitOp + { + public: + DutModeRecvInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (uint16_t& aArg1, nsAutoArrayPtr& aArg2, + uint8_t& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read opcode */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read length */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read data */ + rv = UnpackPDU(pdu, UnpackArray(aArg2, aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + }; + + void DutModeRecvNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + DutModeRecvNotification::Dispatch( + &BluetoothNotificationHandler::DutModeRecvNotification, + DutModeRecvInitOp(aPDU)); + } + + void LeTestModeNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU) + { + LeTestModeNotification::Dispatch( + &BluetoothNotificationHandler::LeTestModeNotification, + UnpackPDUInitOp(aPDU)); + } + + void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) + { + static void (BluetoothDaemonCoreModule::* const HandleNtf[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + INIT_ARRAY_AT(0, &BluetoothDaemonCoreModule::AdapterStateChangedNtf), + INIT_ARRAY_AT(1, &BluetoothDaemonCoreModule::AdapterPropertiesNtf), + INIT_ARRAY_AT(2, &BluetoothDaemonCoreModule::RemoteDevicePropertiesNtf), + INIT_ARRAY_AT(3, &BluetoothDaemonCoreModule::DeviceFoundNtf), + INIT_ARRAY_AT(4, &BluetoothDaemonCoreModule::DiscoveryStateChangedNtf), + INIT_ARRAY_AT(5, &BluetoothDaemonCoreModule::PinRequestNtf), + INIT_ARRAY_AT(6, &BluetoothDaemonCoreModule::SspRequestNtf), + INIT_ARRAY_AT(7, &BluetoothDaemonCoreModule::BondStateChangedNtf), + INIT_ARRAY_AT(8, &BluetoothDaemonCoreModule::AclStateChangedNtf), + INIT_ARRAY_AT(9, &BluetoothDaemonCoreModule::DutModeRecvNtf), + INIT_ARRAY_AT(10, &BluetoothDaemonCoreModule::LeTestModeNtf) + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + uint8_t index = aHeader.mOpcode - 0x81; + + if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) || + NS_WARN_IF(!HandleNtf[index])) { + return; + } + + (this->*(HandleNtf[index]))(aHeader, aPDU); + } + +}; + +// +// Protocol handling +// + +class BluetoothDaemonProtocol MOZ_FINAL + : public BluetoothDaemonPDUConsumer + , public BluetoothDaemonSetupModule + , public BluetoothDaemonCoreModule + , public BluetoothDaemonSocketModule +{ +public: + BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection); + + // Outgoing PDUs + // + + nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) MOZ_OVERRIDE; + + void StoreUserData(const BluetoothDaemonPDU& aPDU) MOZ_OVERRIDE; + + // Incoming PUDs + // + + void Handle(BluetoothDaemonPDU& aPDU) MOZ_OVERRIDE; + + void* FetchUserData(const BluetoothDaemonPDUHeader& aHeader); + +private: + void HandleSetupSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleCoreSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleSocketSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + + BluetoothDaemonConnection* mConnection; + nsTArray mUserDataQ; +}; + +BluetoothDaemonProtocol::BluetoothDaemonProtocol( + BluetoothDaemonConnection* aConnection) + : mConnection(aConnection) +{ + MOZ_ASSERT(mConnection); +} + +nsresult +BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData) +{ + MOZ_ASSERT(aPDU); + + aPDU->SetUserData(aUserData); + aPDU->UpdateHeader(); + return mConnection->Send(aPDU); // Forward PDU to command channel +} + +void +BluetoothDaemonProtocol::HandleSetupSvc( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + BluetoothDaemonSetupModule::HandleSvc(aHeader, aPDU, aUserData); +} + +void +BluetoothDaemonProtocol::HandleCoreSvc( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + BluetoothDaemonCoreModule::HandleSvc(aHeader, aPDU, aUserData); +} + +void +BluetoothDaemonProtocol::HandleSocketSvc( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + BluetoothDaemonSocketModule::HandleSvc(aHeader, aPDU, aUserData); +} + +void +BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) +{ + static void (BluetoothDaemonProtocol::* const HandleSvc[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + INIT_ARRAY_AT(BluetoothDaemonSetupModule::SERVICE_ID, + &BluetoothDaemonProtocol::HandleSetupSvc), + INIT_ARRAY_AT(BluetoothDaemonCoreModule::SERVICE_ID, + &BluetoothDaemonProtocol::HandleCoreSvc), + INIT_ARRAY_AT(BluetoothDaemonSocketModule::SERVICE_ID, + &BluetoothDaemonProtocol::HandleSocketSvc) + }; + + BluetoothDaemonPDUHeader header; + + if (NS_FAILED(UnpackPDU(aPDU, header)) || + NS_WARN_IF(!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc))) || + NS_WARN_IF(!(HandleSvc[header.mService]))) { + return; + } + + (this->*(HandleSvc[header.mService]))(header, aPDU, FetchUserData(header)); +} + +void +BluetoothDaemonProtocol::StoreUserData(const BluetoothDaemonPDU& aPDU) +{ + MOZ_ASSERT(!NS_IsMainThread()); + + mUserDataQ.AppendElement(aPDU.GetUserData()); +} + +void* +BluetoothDaemonProtocol::FetchUserData(const BluetoothDaemonPDUHeader& aHeader) +{ + MOZ_ASSERT(!NS_IsMainThread()); + + if (aHeader.mOpcode & 0x80) { + return nullptr; // Ignore notifications + } + + void* userData = mUserDataQ.ElementAt(0); + mUserDataQ.RemoveElementAt(0); + + return userData; +} + +// +// Channels +// + +class BluetoothDaemonChannel MOZ_FINAL : public BluetoothDaemonConnection +{ +public: + BluetoothDaemonChannel(BluetoothDaemonInterface::Channel aChannel); + + nsresult ConnectSocket(BluetoothDaemonInterface* aInterface, + BluetoothDaemonPDUConsumer* aConsumer); + + // Connection state + // + + void OnConnectSuccess() MOZ_OVERRIDE; + void OnConnectError() MOZ_OVERRIDE; + void OnDisconnect() MOZ_OVERRIDE; + +private: + BluetoothDaemonInterface* mInterface; + BluetoothDaemonInterface::Channel mChannel; +}; + +BluetoothDaemonChannel::BluetoothDaemonChannel( + BluetoothDaemonInterface::Channel aChannel) +: mInterface(nullptr) +, mChannel(aChannel) +{ } + +nsresult +BluetoothDaemonChannel::ConnectSocket(BluetoothDaemonInterface* aInterface, + BluetoothDaemonPDUConsumer* aConsumer) +{ + MOZ_ASSERT(aInterface); + + mInterface = aInterface; + + return BluetoothDaemonConnection::ConnectSocket(aConsumer); +} + +void +BluetoothDaemonChannel::OnConnectSuccess() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mInterface); + + mInterface->OnConnectSuccess(mChannel); +} + +void +BluetoothDaemonChannel::OnConnectError() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mInterface); + + mInterface->OnConnectError(mChannel); + mInterface = nullptr; +} + +void +BluetoothDaemonChannel::OnDisconnect() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mInterface); + + mInterface->OnDisconnect(mChannel); + mInterface = nullptr; +} + +// +// Interface +// + +/* returns the container structure of a variable; _t is the container's + * type, _v the name of the variable, and _m is _v's field within _t + */ +#define container(_t, _v, _m) \ + ( (_t*)( ((const unsigned char*)(_v)) - offsetof(_t, _m) ) ) + +BluetoothDaemonInterface* +BluetoothDaemonInterface::GetInstance() +{ + static BluetoothDaemonInterface* sBluetoothInterface; + + if (sBluetoothInterface) { + return sBluetoothInterface; + } + + // Only create channel objects here. The connection will be + // established by |BluetoothDaemonInterface::Init|. + + BluetoothDaemonChannel* cmdChannel = + new BluetoothDaemonChannel(BluetoothDaemonInterface::CMD_CHANNEL); + + BluetoothDaemonChannel* ntfChannel = + new BluetoothDaemonChannel(BluetoothDaemonInterface::NTF_CHANNEL); + + // Create a new interface object with the channels and a + // protocol handler. + + sBluetoothInterface = + new BluetoothDaemonInterface(cmdChannel, + ntfChannel, + new BluetoothDaemonProtocol(cmdChannel)); + + return sBluetoothInterface; +} + +BluetoothDaemonInterface::BluetoothDaemonInterface( + BluetoothDaemonChannel* aCmdChannel, + BluetoothDaemonChannel* aNtfChannel, + BluetoothDaemonProtocol* aProtocol) +: mCmdChannel(aCmdChannel) +, mNtfChannel(aNtfChannel) +, mProtocol(aProtocol) +{ + MOZ_ASSERT(mCmdChannel); + MOZ_ASSERT(mNtfChannel); + MOZ_ASSERT(mProtocol); +} + +BluetoothDaemonInterface::~BluetoothDaemonInterface() +{ } + +class BluetoothDaemonInterface::InitResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + InitResultHandler(BluetoothDaemonInterface* aInterface, + BluetoothResultHandler* aRes) + : mInterface(aInterface) + , mRes(aRes) + , mRegisteredSocketModule(false) + { + MOZ_ASSERT(mInterface); + } + + // We need to call methods from the |BluetoothResultHandler|. Since + // we're already on the main thread and returned from Init, we don't + // need to dispatch a new runnable. + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + if (mRes) { + mRes->OnError(aStatus); + } + } + + void RegisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mInterface->mProtocol); + + if (!mRegisteredSocketModule) { + mRegisteredSocketModule = true; + // Init, step 4: Register Socket module + mInterface->mProtocol->RegisterModuleCmd( + BluetoothDaemonSocketModule::SERVICE_ID, 0x00, this); + } else if (mRes) { + // Init, step 5: Signal success to caller + mRes->Init(); + } + } + +private: + BluetoothDaemonInterface* mInterface; + nsRefPtr mRes; + bool mRegisteredSocketModule; +}; + +void +BluetoothDaemonInterface::OnConnectSuccess(enum Channel aChannel) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); + + switch (aChannel) { + case CMD_CHANNEL: + // Init, step 2: Connect notification channel... + if (mNtfChannel->GetConnectionStatus() != SOCKET_CONNECTED) { + nsresult rv = mNtfChannel->ConnectSocket(this, mProtocol); + if (NS_FAILED(rv)) { + OnConnectError(NTF_CHANNEL); + } + } else { + // ...or go to step 3 if channel is already connected. + OnConnectSuccess(NTF_CHANNEL); + } + break; + + case NTF_CHANNEL: { + nsRefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + + // Init, step 3: Register Core module + nsresult rv = mProtocol->RegisterModuleCmd( + BluetoothDaemonCoreModule::SERVICE_ID, 0x00, + new InitResultHandler(this, res)); + if (NS_FAILED(rv) && res) { + DispatchError(res, STATUS_FAIL); + } + } + break; + } +} + +void +BluetoothDaemonInterface::OnConnectError(enum Channel aChannel) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); + + switch (aChannel) { + case NTF_CHANNEL: + // Close command channel + mCmdChannel->CloseSocket(); + /* fall through for cleanup and error signalling */ + case CMD_CHANNEL: { + // Signal error to caller + nsRefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + + if (res) { + DispatchError(res, STATUS_FAIL); + } + } + break; + } +} + +void +BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); + + switch (aChannel) { + case NTF_CHANNEL: + // Cleanup, step 4: Close command channel + mCmdChannel->CloseSocket(); + break; + case CMD_CHANNEL: { + nsRefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + + // Cleanup, step 5: Signal success to caller + if (res) { + res->Cleanup(); + } + } + break; + } +} + +void +BluetoothDaemonInterface::Init( + BluetoothNotificationHandler* aNotificationHandler, + BluetoothResultHandler* aRes) +{ + sNotificationHandler = aNotificationHandler; + + mResultHandlerQ.AppendElement(aRes); + + // Init, step 1: Connect command channel... + if (mCmdChannel->GetConnectionStatus() != SOCKET_CONNECTED) { + nsresult rv = mCmdChannel->ConnectSocket(this, mProtocol); + if (NS_FAILED(rv)) { + OnConnectError(CMD_CHANNEL); + } + } else { + // ...or go to step 2 if channel is already connected. + OnConnectSuccess(CMD_CHANNEL); + } +} + +class BluetoothDaemonInterface::CleanupResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + CleanupResultHandler(BluetoothDaemonInterface* aInterface) + : mInterface(aInterface) + , mUnregisteredCoreModule(false) + { + MOZ_ASSERT(mInterface); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + Proceed(); + } + + void UnregisterModule() MOZ_OVERRIDE + { + Proceed(); + } + +private: + void Proceed() + { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mInterface->mProtocol); + + if (!mUnregisteredCoreModule) { + mUnregisteredCoreModule = true; + // Cleanup, step 2: Unregister Core module + mInterface->mProtocol->UnregisterModuleCmd( + BluetoothDaemonCoreModule::SERVICE_ID, this); + } else { + // Cleanup, step 3: Close notification channel + mInterface->mNtfChannel->CloseSocket(); + } + } + + BluetoothDaemonInterface* mInterface; + bool mUnregisteredCoreModule; +}; + +void +BluetoothDaemonInterface::Cleanup(BluetoothResultHandler* aRes) +{ + sNotificationHandler = nullptr; + + mResultHandlerQ.AppendElement(aRes); + + // Cleanup, step 1: Unregister Socket module + mProtocol->UnregisterModuleCmd( + BluetoothDaemonSocketModule::SERVICE_ID, new CleanupResultHandler(this)); +} + +void +BluetoothDaemonInterface::Enable(BluetoothResultHandler* aRes) +{ + static_cast(mProtocol)->EnableCmd(aRes); +} + +void +BluetoothDaemonInterface::Disable(BluetoothResultHandler* aRes) +{ + static_cast(mProtocol)->DisableCmd(aRes); +} + +/* Adapter Properties */ + +void +BluetoothDaemonInterface::GetAdapterProperties(BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->GetAdapterPropertiesCmd(aRes); +} + +void +BluetoothDaemonInterface::GetAdapterProperty(const nsAString& aName, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->GetAdapterPropertyCmd(aName, aRes); +} + +void +BluetoothDaemonInterface::SetAdapterProperty( + const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->SetAdapterPropertyCmd(aProperty, aRes); +} + +/* Remote Device Properties */ + +void +BluetoothDaemonInterface::GetRemoteDeviceProperties( + const nsAString& aRemoteAddr, BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->GetRemoteDevicePropertiesCmd(aRemoteAddr, aRes); +} + +void +BluetoothDaemonInterface::GetRemoteDeviceProperty( + const nsAString& aRemoteAddr, const nsAString& aName, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->GetRemoteDevicePropertyCmd(aRemoteAddr, aName, aRes); +} + +void +BluetoothDaemonInterface::SetRemoteDeviceProperty( + const nsAString& aRemoteAddr, const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->SetRemoteDevicePropertyCmd(aRemoteAddr, aProperty, aRes); +} + +/* Remote Services */ + +void +BluetoothDaemonInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr, + const uint8_t aUuid[16], + BluetoothResultHandler* aRes) +{ + static_cast( + mProtocol)->GetRemoteServiceRecordCmd(aRemoteAddr, aUuid, aRes); +} + +void +BluetoothDaemonInterface::GetRemoteServices(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes) +{ + static_cast( + mProtocol)->GetRemoteServicesCmd(aRemoteAddr, aRes); +} + +/* Discovery */ + +void +BluetoothDaemonInterface::StartDiscovery(BluetoothResultHandler* aRes) +{ + static_cast(mProtocol)->StartDiscoveryCmd(aRes); +} + +void +BluetoothDaemonInterface::CancelDiscovery(BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->CancelDiscoveryCmd(aRes); +} + +/* Bonds */ + +void +BluetoothDaemonInterface::CreateBond(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->CreateBondCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonInterface::RemoveBond(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->RemoveBondCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonInterface::CancelBond(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->CancelBondCmd(aBdAddr, aRes); +} + +/* Authentication */ + +void +BluetoothDaemonInterface::PinReply(const nsAString& aBdAddr, bool aAccept, + const nsAString& aPinCode, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->PinReplyCmd(aBdAddr, aAccept, aPinCode, aRes); +} + +void +BluetoothDaemonInterface::SspReply(const nsAString& aBdAddr, + const nsAString& aVariant, + bool aAccept, uint32_t aPasskey, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->SspReplyCmd(aBdAddr, aVariant, aAccept, aPasskey, aRes); +} + +/* DUT Mode */ + +void +BluetoothDaemonInterface::DutModeConfigure(bool aEnable, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->DutModeConfigureCmd(aEnable, aRes); +} + +void +BluetoothDaemonInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, + uint8_t aLen, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->DutModeSendCmd(aOpcode, aBuf, aLen, aRes); +} + +/* LE Mode */ + +void +BluetoothDaemonInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, + uint8_t aLen, + BluetoothResultHandler* aRes) +{ + static_cast + (mProtocol)->LeTestModeCmd(aOpcode, aBuf, aLen, aRes); +} + +void +BluetoothDaemonInterface::DispatchError(BluetoothResultHandler* aRes, + BluetoothStatus aStatus) +{ + BluetoothResultRunnable1< + BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus>::Dispatch( + aRes, &BluetoothResultHandler::OnError, + ConstantInitOp1(aStatus)); +} + +// Profile Interfaces +// + +BluetoothSocketInterface* +BluetoothDaemonInterface::GetBluetoothSocketInterface() +{ + if (mSocketInterface) { + return mSocketInterface; + } + + mSocketInterface = new BluetoothDaemonSocketInterface(mProtocol); + + return mSocketInterface; +} + +BluetoothHandsfreeInterface* +BluetoothDaemonInterface::GetBluetoothHandsfreeInterface() +{ + return nullptr; +} + +BluetoothA2dpInterface* +BluetoothDaemonInterface::GetBluetoothA2dpInterface() +{ + return nullptr; +} + +BluetoothAvrcpInterface* +BluetoothDaemonInterface::GetBluetoothAvrcpInterface() +{ + return nullptr; +} + +BluetoothGattInterface* +BluetoothDaemonInterface::GetBluetoothGattInterface() +{ + return nullptr; +} + +END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,133 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothdaemoninterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemoninterface_h__ + +#include "BluetoothInterface.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothDaemonChannel; +class BluetoothDaemonProtocol; +class BluetoothDaemonSocketInterface; + +class BluetoothDaemonInterface MOZ_FINAL : public BluetoothInterface +{ +public: + class CleanupResultHandler; + class InitResultHandler; + + friend class BluetoothDaemonChannel; + friend class CleanupResultHandler; + friend class InitResultHandler; + + static BluetoothDaemonInterface* GetInstance(); + + void Init(BluetoothNotificationHandler* aNotificationHandler, + BluetoothResultHandler* aRes); + void Cleanup(BluetoothResultHandler* aRes); + + void Enable(BluetoothResultHandler* aRes); + void Disable(BluetoothResultHandler* aRes); + + /* Adapter Properties */ + + void GetAdapterProperties(BluetoothResultHandler* aRes); + void GetAdapterProperty(const nsAString& aName, + BluetoothResultHandler* aRes); + void SetAdapterProperty(const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes); + + /* Remote Device Properties */ + + void GetRemoteDeviceProperties(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes); + void GetRemoteDeviceProperty(const nsAString& aRemoteAddr, + const nsAString& aName, + BluetoothResultHandler* aRes); + void SetRemoteDeviceProperty(const nsAString& aRemoteAddr, + const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes); + + /* Remote Services */ + + void GetRemoteServiceRecord(const nsAString& aRemoteAddr, + const uint8_t aUuid[16], + BluetoothResultHandler* aRes); + void GetRemoteServices(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes); + + /* Discovery */ + + void StartDiscovery(BluetoothResultHandler* aRes); + void CancelDiscovery(BluetoothResultHandler* aRes); + + /* Bonds */ + + void CreateBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes); + void RemoveBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes); + void CancelBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes); + + /* Authentication */ + + void PinReply(const nsAString& aBdAddr, bool aAccept, + const nsAString& aPinCode, + BluetoothResultHandler* aRes); + + void SspReply(const nsAString& aBdAddr, const nsAString& aVariant, + bool aAccept, uint32_t aPasskey, + BluetoothResultHandler* aRes); + + /* DUT Mode */ + + void DutModeConfigure(bool aEnable, BluetoothResultHandler* aRes); + void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes); + + /* LE Mode */ + + void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes); + + /* Profile Interfaces */ + + BluetoothSocketInterface* GetBluetoothSocketInterface() MOZ_OVERRIDE; + BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface() MOZ_OVERRIDE; + BluetoothA2dpInterface* GetBluetoothA2dpInterface() MOZ_OVERRIDE; + BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() MOZ_OVERRIDE; + BluetoothGattInterface* GetBluetoothGattInterface() MOZ_OVERRIDE; + +protected: + enum Channel { + CMD_CHANNEL, + NTF_CHANNEL + }; + + BluetoothDaemonInterface(BluetoothDaemonChannel* aCmdChannel, + BluetoothDaemonChannel* aNtfChannel, + BluetoothDaemonProtocol* aProtocol); + ~BluetoothDaemonInterface(); + + void OnConnectSuccess(enum Channel aChannel); + void OnConnectError(enum Channel aChannel); + void OnDisconnect(enum Channel aChannel); + +private: + void DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus); + + nsAutoPtr mCmdChannel; + nsAutoPtr mNtfChannel; + nsAutoPtr mProtocol; + + nsTArray > mResultHandlerQ; + + nsAutoPtr mSocketInterface; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,32 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "BluetoothDaemonSetupInterface.h" + +BEGIN_BLUETOOTH_NAMESPACE + +BluetoothSetupResultHandler::~BluetoothSetupResultHandler() +{ } + +void +BluetoothSetupResultHandler::OnError(BluetoothStatus aStatus) +{ + BT_WARNING("Received error code %d", (int)aStatus); +} + +void +BluetoothSetupResultHandler::RegisterModule() +{ } + +void +BluetoothSetupResultHandler::UnregisterModule() +{ } + +void +BluetoothSetupResultHandler::Configuration() +{ } + +END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.h 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,29 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothdaemonsetupinterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemonsetupinterface_h__ + +#include "BluetoothCommon.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothSetupResultHandler +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothSetupResultHandler) + + virtual ~BluetoothSetupResultHandler(); + + virtual void OnError(BluetoothStatus aStatus); + virtual void RegisterModule(); + virtual void UnregisterModule(); + virtual void Configuration(); +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,352 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "BluetoothDaemonSocketInterface.h" +#include "BluetoothSocketMessageWatcher.h" +#include "nsXULAppAPI.h" +#include "mozilla/unused.h" + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Socket module +// + +// Commands +// + +nsresult +BluetoothDaemonSocketModule::ListenCmd(BluetoothSocketType aType, + const nsAString& aServiceName, + const uint8_t aServiceUuid[16], + int aChannel, bool aEncrypt, + bool aAuth, + BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new BluetoothDaemonPDU( + SERVICE_ID, OPCODE_LISTEN, 0)); + + nsresult rv = PackPDU( + aType, + PackConversion(aServiceName), + PackArray(aServiceUuid, 16), + PackConversion(aChannel), + SocketFlags(aEncrypt, aAuth), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonSocketModule::ConnectCmd(const nsAString& aBdAddr, + BluetoothSocketType aType, + const uint8_t aUuid[16], + int aChannel, bool aEncrypt, + bool aAuth, + BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new BluetoothDaemonPDU( + SERVICE_ID, OPCODE_CONNECT, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), + aType, + PackArray(aUuid, 16), + PackConversion(aChannel), + SocketFlags(aEncrypt, aAuth), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +/* |DeleteTask| deletes a class instance on the I/O thread + */ +template +class DeleteTask MOZ_FINAL : public Task +{ +public: + DeleteTask(T* aPtr) + : mPtr(aPtr) + { } + + void Run() MOZ_OVERRIDE + { + mPtr = nullptr; + } + +private: + nsAutoPtr mPtr; +}; + +/* |AcceptWatcher| specializes SocketMessageWatcher for Accept + * operations by reading the socket messages from Bluedroid and + * forwarding the received client socket to the resource handler. + * The first message is received immediately. When there's a new + * connection, Bluedroid sends the 2nd message with the socket + * info and socket file descriptor. + */ +class BluetoothDaemonSocketModule::AcceptWatcher MOZ_FINAL + : public SocketMessageWatcher +{ +public: + AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes) + : SocketMessageWatcher(aFd, aRes) + { } + + void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE + { + if (aStatus == STATUS_SUCCESS) { + IntStringIntResultRunnable::Dispatch( + GetResultHandler(), &BluetoothSocketResultHandler::Accept, + ConstantInitOp3(GetClientFd(), GetBdAddress(), + GetConnectionStatus())); + } else { + ErrorRunnable::Dispatch(GetResultHandler(), + &BluetoothSocketResultHandler::OnError, + ConstantInitOp1(aStatus)); + } + + MessageLoopForIO::current()->PostTask( + FROM_HERE, new DeleteTask(this)); + } +}; + +nsresult +BluetoothDaemonSocketModule::AcceptCmd(int aFd, + BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + /* receive Bluedroid's socket-setup messages and client fd */ + Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes)); + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); + + return NS_OK; +} + +nsresult +BluetoothDaemonSocketModule::CloseCmd(BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + /* stop the watcher corresponding to |aRes| */ + Task* t = new DeleteSocketMessageWatcherTask(aRes); + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); + + return NS_OK; +} + +void +BluetoothDaemonSocketModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonSocketModule::* const HandleRsp[])( + const BluetoothDaemonPDUHeader&, + BluetoothDaemonPDU&, + BluetoothSocketResultHandler*) = { + INIT_ARRAY_AT(OPCODE_ERROR, &BluetoothDaemonSocketModule::ErrorRsp), + INIT_ARRAY_AT(OPCODE_LISTEN, &BluetoothDaemonSocketModule::ListenRsp), + INIT_ARRAY_AT(OPCODE_CONNECT, &BluetoothDaemonSocketModule::ConnectRsp), + }; + + if (NS_WARN_IF(MOZ_ARRAY_LENGTH(HandleRsp) <= aHeader.mOpcode) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + + if (!res) { + return; // Return early if no result handler has been set + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +nsresult +BluetoothDaemonSocketModule::Send(BluetoothDaemonPDU* aPDU, + BluetoothSocketResultHandler* aRes) +{ + aRes->AddRef(); // Keep reference for response + return Send(aPDU, static_cast(aRes)); +} + +uint8_t +BluetoothDaemonSocketModule::SocketFlags(bool aEncrypt, bool aAuth) +{ + return (0x01 * aEncrypt) | (0x02 * aAuth); +} + +// Responses +// + +void +BluetoothDaemonSocketModule::ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSocketResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &BluetoothSocketResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +class BluetoothDaemonSocketModule::ListenInitOp MOZ_FINAL : private PDUInitOp +{ +public: + ListenInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + aArg1 = pdu.AcquireFd(); + + if (NS_WARN_IF(aArg1 < 0)) { + return NS_ERROR_ILLEGAL_VALUE; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonSocketModule::ListenRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSocketResultHandler* aRes) +{ + IntResultRunnable::Dispatch( + aRes, &BluetoothSocketResultHandler::Listen, ListenInitOp(aPDU)); +} + +/* |ConnectWatcher| specializes SocketMessageWatcher for + * connect operations by reading the socket messages from + * Bluedroid and forwarding the connected socket to the + * resource handler. + */ +class BluetoothDaemonSocketModule::ConnectWatcher MOZ_FINAL + : public SocketMessageWatcher +{ +public: + ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes) + : SocketMessageWatcher(aFd, aRes) + { } + + void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE + { + if (aStatus == STATUS_SUCCESS) { + IntStringIntResultRunnable::Dispatch( + GetResultHandler(), &BluetoothSocketResultHandler::Connect, + ConstantInitOp3(GetFd(), GetBdAddress(), + GetConnectionStatus())); + } else { + ErrorRunnable::Dispatch(GetResultHandler(), + &BluetoothSocketResultHandler::OnError, + ConstantInitOp1(aStatus)); + } + + MessageLoopForIO::current()->PostTask( + FROM_HERE, new DeleteTask(this)); + } +}; + +void +BluetoothDaemonSocketModule::ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSocketResultHandler* aRes) +{ + /* the file descriptor is attached in the PDU's ancillary data */ + int fd = aPDU.AcquireFd(); + if (fd < 0) { + ErrorRunnable::Dispatch(aRes, &BluetoothSocketResultHandler::OnError, + ConstantInitOp1(STATUS_FAIL)); + return; + } + + /* receive Bluedroid's socket-setup messages */ + Task* t = new SocketMessageWatcherTask(new ConnectWatcher(fd, aRes)); + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); +} + +// +// Socket interface +// + +BluetoothDaemonSocketInterface::BluetoothDaemonSocketInterface( + BluetoothDaemonSocketModule* aModule) +: mModule(aModule) +{ + MOZ_ASSERT(mModule); +} + +BluetoothDaemonSocketInterface::~BluetoothDaemonSocketInterface() +{ } + +void +BluetoothDaemonSocketInterface::Listen(BluetoothSocketType aType, + const nsAString& aServiceName, + const uint8_t aServiceUuid[16], + int aChannel, bool aEncrypt, + bool aAuth, + BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ListenCmd(aType, aServiceName, aServiceUuid, aChannel, + aEncrypt, aAuth, aRes); +} + +void +BluetoothDaemonSocketInterface::Connect(const nsAString& aBdAddr, + BluetoothSocketType aType, + const uint8_t aUuid[16], + int aChannel, bool aEncrypt, + bool aAuth, + BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ConnectCmd(aBdAddr, aType, aUuid, aChannel, aEncrypt, aAuth, aRes); +} + +void +BluetoothDaemonSocketInterface::Accept(int aFd, + BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->AcceptCmd(aFd, aRes); +} + +void +BluetoothDaemonSocketInterface::Close(BluetoothSocketResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->CloseCmd(aRes); +} + +END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.h 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,129 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothdaemonsocketinterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemonsocketinterface_h__ + +#include "BluetoothDaemonHelpers.h" +#include "BluetoothInterface.h" +#include "BluetoothInterfaceHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +using namespace mozilla::ipc; + +class BlutoothDaemonInterface; + +class BluetoothDaemonSocketModule +{ +public: + enum { + SERVICE_ID = 0x02 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_LISTEN = 0x01, + OPCODE_CONNECT = 0x02 + }; + + virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + + // Commands + // + + nsresult ListenCmd(BluetoothSocketType aType, + const nsAString& aServiceName, + const uint8_t aServiceUuid[16], + int aChannel, bool aEncrypt, bool aAuth, + BluetoothSocketResultHandler* aRes); + + nsresult ConnectCmd(const nsAString& aBdAddr, + BluetoothSocketType aType, + const uint8_t aUuid[16], + int aChannel, bool aEncrypt, bool aAuth, + BluetoothSocketResultHandler* aRes); + + nsresult AcceptCmd(int aFd, BluetoothSocketResultHandler* aRes); + + nsresult CloseCmd(BluetoothSocketResultHandler* aRes); + +protected: + + void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + + nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothSocketResultHandler* aRes); + +private: + class AcceptWatcher; + class ConnectWatcher; + class ListenInitOp; + + uint8_t SocketFlags(bool aEncrypt, bool aAuth); + + // Responses + // + + typedef BluetoothResultRunnable0 + ResultRunnable; + + typedef BluetoothResultRunnable1 + IntResultRunnable; + + typedef BluetoothResultRunnable1 + ErrorRunnable; + + typedef BluetoothResultRunnable3 + IntStringIntResultRunnable; + + void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSocketResultHandler* aRes); + + void ListenRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSocketResultHandler* aRes); + + void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothSocketResultHandler* aRes); +}; + +class BluetoothDaemonSocketInterface MOZ_FINAL + : public BluetoothSocketInterface +{ +public: + BluetoothDaemonSocketInterface(BluetoothDaemonSocketModule* aModule); + ~BluetoothDaemonSocketInterface(); + + void Listen(BluetoothSocketType aType, + const nsAString& aServiceName, + const uint8_t aServiceUuid[16], + int aChannel, bool aEncrypt, bool aAuth, + BluetoothSocketResultHandler* aRes); + + void Connect(const nsAString& aBdAddr, + BluetoothSocketType aType, + const uint8_t aUuid[16], + int aChannel, bool aEncrypt, bool aAuth, + BluetoothSocketResultHandler* aRes); + + void Accept(int aFd, BluetoothSocketResultHandler* aRes); + + void Close(BluetoothSocketResultHandler* aRes); + +private: + BluetoothDaemonSocketModule* mModule; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothCommon.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothCommon.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothCommon.h 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothCommon.h 2014-11-26 21:45:56.000000000 +0000 @@ -18,14 +18,17 @@ #if MOZ_IS_GCC && MOZ_GCC_VERSION_AT_LEAST(4, 7, 0) /* use designated array initializers if supported */ -#define CONVERT(in_, out_) \ +#define INIT_ARRAY_AT(in_, out_) \ [in_] = out_ #else /* otherwise init array element by position */ -#define CONVERT(in_, out_) \ +#define INIT_ARRAY_AT(in_, out_) \ out_ #endif +#define CONVERT(in_, out_) \ + INIT_ARRAY_AT(in_, out_) + #undef BT_LOG #if defined(MOZ_WIDGET_GONK) #include diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothInterface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothInterface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothInterface.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothInterface.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -8,6 +8,9 @@ #ifdef MOZ_B2G_BT_BLUEDROID #include "BluetoothHALInterface.h" #endif +#ifdef MOZ_B2G_BT_DAEMON +#include "BluetoothDaemonInterface.h" +#endif BEGIN_BLUETOOTH_NAMESPACE @@ -124,15 +127,19 @@ BluetoothInterface::GetInstance() { /* Here's where we decide which implementation to use. Currently - * there is only Bluedroid, but others are possible. Having multiple - * interfaces built-in and selecting the correct one at runtime could - * also be an option. + * there is only Bluedroid and the Bluetooth daemon, but others are + * possible. Having multiple interfaces built-in and selecting the + * correct one at runtime could also be an option. */ #ifdef MOZ_B2G_BT_BLUEDROID return BluetoothHALInterface::GetInstance(); #else +#ifdef MOZ_B2G_BT_DAEMON + return BluetoothDaemonInterface::GetInstance(); +#else return nullptr; #endif +#endif } BluetoothInterface::BluetoothInterface() diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothInterfaceHelpers.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothInterfaceHelpers.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothInterfaceHelpers.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothInterfaceHelpers.h 2014-11-26 21:45:56.000000000 +0000 @@ -0,0 +1,759 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluetoothinterfacehelpers_h +#define mozilla_dom_bluetooth_bluetoothinterfacehelpers_h + +#include "BluetoothCommon.h" +#include "nsThreadUtils.h" + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Result handling +// +// The classes of type |BluetoothResultRunnable[0..3]| transfer +// a result handler from the I/O thread to the main thread for +// execution. Call the methods |Create| and |Dispatch| to create or +// create-and-dispatch a result runnable. +// +// You need to specify the called method. The |Create| and |Dispatch| +// methods of |BluetoothResultRunnable[1..3]| receive an extra argument +// for initializing the result's arguments. During creation, the result +// runnable calls the supplied class's call operator with the result's +// argument. This is where initialization and conversion from backend- +// specific types is performed. +// + +template +class BluetoothResultRunnable0 : public nsRunnable +{ +public: + typedef BluetoothResultRunnable0 SelfType; + + template + static already_AddRefed + Create(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aObj, aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aObj, aMethod, aInitOp); + if (!runnable) { + BT_LOGR("BluetoothResultRunnable0::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_LOGR("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + ((*mObj).*mMethod)(); + return NS_OK; + } + +private: + BluetoothResultRunnable0(Obj* aObj, Res (Obj::*aMethod)()) + : mObj(aObj) + , mMethod(aMethod) + { + MOZ_ASSERT(mObj); + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + return aInitOp(); + } + + nsRefPtr mObj; + void (Obj::*mMethod)(); +}; + +template +class BluetoothResultRunnable1 : public nsRunnable +{ +public: + typedef BluetoothResultRunnable1 SelfType; + + template + static already_AddRefed + Create(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aObj, aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aObj, aMethod, aInitOp); + if (!runnable) { + BT_LOGR("BluetoothResultRunnable1::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_LOGR("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + ((*mObj).*mMethod)(mArg1); + return NS_OK; + } + +private: + BluetoothResultRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1)) + : mObj(aObj) + , mMethod(aMethod) + { + MOZ_ASSERT(mObj); + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + return aInitOp(mArg1); + } + + nsRefPtr mObj; + Res (Obj::*mMethod)(Arg1); + Tin1 mArg1; +}; + +template +class BluetoothResultRunnable3 : public nsRunnable +{ +public: + typedef BluetoothResultRunnable3 SelfType; + + template + static already_AddRefed + Create(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3), + const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aObj, aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3), + const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aObj, aMethod, aInitOp); + if (!runnable) { + BT_LOGR("BluetoothResultRunnable3::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + ((*mObj).*mMethod)(mArg1, mArg2, mArg3); + return NS_OK; + } + +private: + BluetoothResultRunnable3(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3)) + : mObj(aObj) + , mMethod(aMethod) + { + MOZ_ASSERT(mObj); + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + return aInitOp(mArg1, mArg2, mArg3); + } + + nsRefPtr mObj; + Res (Obj::*mMethod)(Arg1, Arg2, Arg3); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; +}; + +// +// Notification handling +// +// The classes of type |BluetoothNotificationRunnable[0..5]| transfer +// a notification from the I/O thread to a notification handler on the +// main thread. Call the methods |Create| and |Dispatch| to create or +// create-and-dispatch a notification runnable. +// +// Like with result runnables, you need to specify the called method. +// And like with result runnables, the |Create| and |Dispatch| methods +// of |BluetoothNotificationRunnable[1..5]| receive an extra argument +// for initializing the notification's arguments. During creation, the +// notification runnable calls the class's call operator with the +// notification's argument. This is where initialization and conversion +// from backend-specific types is performed. +// + +template +class BluetoothNotificationRunnable0 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable0 SelfType; + + template + static already_AddRefed + Create(Res (ObjectType::*aMethod)(), const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(), const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable0::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable0(Res (ObjectType::*aMethod)()) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + return aInitOp(); + } + + Res (ObjectType::*mMethod)(); +}; + +template +class BluetoothNotificationRunnable1 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable1 SelfType; + + template + static already_AddRefed + Create(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable1::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable1(Res (ObjectType::*aMethod)(Arg1)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1); + Tin1 mArg1; +}; + +template +class BluetoothNotificationRunnable2 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable2 SelfType; + + template + static already_AddRefed + Create(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable2::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable2( + Res (ObjectType::*aMethod)(Arg1, Arg2)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2); + Tin1 mArg1; + Tin2 mArg2; +}; + +template +class BluetoothNotificationRunnable3 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable3 SelfType; + + template + static already_AddRefed + Create(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), + const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable3::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable3( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2, mArg3); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; +}; + +template +class BluetoothNotificationRunnable4 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable4 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), + const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), + const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable4::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable4( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; +}; + +template +class BluetoothNotificationRunnable5 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable5 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), + const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), + const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable5::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable5( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, mArg5); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; +}; + +// +// Init operators +// +// Below are general-purpose init operators for Bluetooth. The classes +// of type |ConstantInitOp[1..3]| initialize results or notifications +// with constant values. +// + +template +class ConstantInitOp1 MOZ_FINAL +{ +public: + ConstantInitOp1(const T1& aArg1) + : mArg1(aArg1) + { } + + nsresult operator () (T1& aArg1) const + { + aArg1 = mArg1; + + return NS_OK; + } + +private: + const T1& mArg1; +}; + +template +class ConstantInitOp2 MOZ_FINAL +{ +public: + ConstantInitOp2(const T1& aArg1, const T2& aArg2) + : mArg1(aArg1) + , mArg2(aArg2) + { } + + nsresult operator () (T1& aArg1, T2& aArg2) const + { + aArg1 = mArg1; + aArg2 = mArg2; + + return NS_OK; + } + +private: + const T1& mArg1; + const T2& mArg2; +}; + +template +class ConstantInitOp3 MOZ_FINAL +{ +public: + ConstantInitOp3(const T1& aArg1, const T2& aArg2, const T3& aArg3) + : mArg1(aArg1) + , mArg2(aArg2) + , mArg3(aArg3) + { } + + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3) const + { + aArg1 = mArg1; + aArg2 = mArg2; + aArg3 = mArg3; + + return NS_OK; + } + +private: + const T1& mArg1; + const T2& mArg2; + const T3& mArg3; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/BluetoothService.cpp 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/BluetoothService.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -52,6 +52,13 @@ /** * B2G bluedroid: * MOZ_B2G_BT and MOZ_B2G_BT_BLUEDROID are both defined; + * MOZ_B2G_BLUEZ or MOZ_B2G_DAEMON are not defined. + */ +#include "BluetoothServiceBluedroid.h" +#elif defined(MOZ_B2G_BT_DAEMON) +/** + * B2G Bluetooth daemon: + * MOZ_B2G_BT, MOZ_B2G_BLUEDROID and MOZ_B2G_BT_DAEMON are defined; * MOZ_B2G_BLUEZ is not defined. */ #include "BluetoothServiceBluedroid.h" @@ -228,6 +235,8 @@ return new BluetoothDBusService(); #elif defined(MOZ_B2G_BT_BLUEDROID) return new BluetoothServiceBluedroid(); +#elif defined(MOZ_B2G_BT_DAEMON) + return new BluetoothServiceBluedroid(); #endif #elif defined(MOZ_BLUETOOTH_DBUS) return new BluetoothDBusService(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/bluetooth2/moz.build 2014-11-14 09:37:21.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/bluetooth2/moz.build 2014-11-26 21:45:56.000000000 +0000 @@ -51,6 +51,10 @@ 'bluedroid/BluetoothA2dpHALInterface.cpp', 'bluedroid/BluetoothA2dpManager.cpp', 'bluedroid/BluetoothAvrcpHALInterface.cpp', + 'bluedroid/BluetoothDaemonHelpers.cpp', + 'bluedroid/BluetoothDaemonInterface.cpp', + 'bluedroid/BluetoothDaemonSetupInterface.cpp', + 'bluedroid/BluetoothDaemonSocketInterface.cpp', 'bluedroid/BluetoothGattHALInterface.cpp', 'bluedroid/BluetoothGattManager.cpp', 'bluedroid/BluetoothHALHelpers.cpp', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraControlImpl.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraControlImpl.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraControlImpl.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraControlImpl.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -22,6 +22,7 @@ , mCameraId(aCameraId) , mPreviewState(CameraControlListener::kPreviewStopped) , mHardwareState(CameraControlListener::kHardwareClosed) + , mHardwareStateChangeReason(NS_OK) { DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); @@ -71,7 +72,8 @@ } void -CameraControlImpl::OnHardwareStateChange(CameraControlListener::HardwareState aNewState) +CameraControlImpl::OnHardwareStateChange(CameraControlListener::HardwareState aNewState, + nsresult aReason) { // This callback can run on threads other than the Main Thread and // the Camera Thread. On Gonk, it may be called from the camera's @@ -84,20 +86,22 @@ } #ifdef PR_LOGGING - const char* state[] = { "open", "closed", "failed" }; + const char* state[] = { "closed", "open", "failed" }; MOZ_ASSERT(aNewState >= 0); if (static_cast(aNewState) < sizeof(state) / sizeof(state[0])) { - DOM_CAMERA_LOGI("New hardware state is '%s'\n", state[aNewState]); + DOM_CAMERA_LOGI("New hardware state is '%s' (reason=0x%x)\n", + state[aNewState], aReason); } else { DOM_CAMERA_LOGE("OnHardwareStateChange: got invalid HardwareState value %d\n", aNewState); } #endif mHardwareState = aNewState; + mHardwareStateChangeReason = aReason; for (uint32_t i = 0; i < mListeners.Length(); ++i) { CameraControlListener* l = mListeners[i]; - l->OnHardwareStateChange(mHardwareState); + l->OnHardwareStateChange(mHardwareState, mHardwareStateChangeReason); } } @@ -183,19 +187,6 @@ } void -CameraControlImpl::OnClosed() -{ - // This callback can run on threads other than the Main Thread and - // the Camera Thread. - RwLockAutoEnterRead lock(mListenerLock); - - for (uint32_t i = 0; i < mListeners.Length(); ++i) { - CameraControlListener* l = mListeners[i]; - l->OnHardwareStateChange(CameraControlListener::kHardwareClosed); - } -} - -void CameraControlImpl::OnRecorderStateChange(CameraControlListener::RecorderState aState, int32_t aStatus, int32_t aTrackNumber) { @@ -706,7 +697,7 @@ // Update the newly-added listener's state l->OnConfigurationChange(mCurrentConfiguration); - l->OnHardwareStateChange(mHardwareState); + l->OnHardwareStateChange(mHardwareState, mHardwareStateChangeReason); l->OnPreviewStateChange(mPreviewState); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraControlImpl.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraControlImpl.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraControlImpl.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraControlImpl.h 2014-11-26 21:45:56.000000000 +0000 @@ -53,7 +53,6 @@ // Event handlers called directly from outside this class. void OnShutter(); - void OnClosed(); void OnUserError(CameraControlListener::UserContext aContext, nsresult aError); void OnSystemError(CameraControlListener::SystemContext aContext, nsresult aError); void OnAutoFocusMoving(bool aIsMoving); @@ -69,7 +68,8 @@ void OnRecorderStateChange(CameraControlListener::RecorderState aState, int32_t aStatus = -1, int32_t aTrackNumber = -1); void OnPreviewStateChange(CameraControlListener::PreviewState aState); - void OnHardwareStateChange(CameraControlListener::HardwareState aState); + void OnHardwareStateChange(CameraControlListener::HardwareState aState, + nsresult aReason); void OnConfigurationChange(); // When we create a new CameraThread, we keep a static reference to it so @@ -134,6 +134,7 @@ CameraControlListener::PreviewState mPreviewState; CameraControlListener::HardwareState mHardwareState; + nsresult mHardwareStateChangeReason; private: CameraControlImpl(const CameraControlImpl&) MOZ_DELETE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraControlListener.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraControlListener.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraControlListener.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraControlListener.h 2014-11-26 21:45:56.000000000 +0000 @@ -38,7 +38,14 @@ kHardwareOpen, kHardwareOpenFailed }; - virtual void OnHardwareStateChange(HardwareState aState) { } + // aReason: + // NS_OK : state change was expected and normal; + // NS_ERROR_FAILURE : one or more system-level components failed and + // the camera was closed; + // NS_ERROR_NOT_AVAILABLE : the hardware is in use by another process + // and cannot be acquired, or another process + // was given access to the camera hardware. + virtual void OnHardwareStateChange(HardwareState aState, nsresult aReason) { } enum PreviewState { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraPreviewMediaStream.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraPreviewMediaStream.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/CameraPreviewMediaStream.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/CameraPreviewMediaStream.h 2014-11-26 21:45:56.000000000 +0000 @@ -16,7 +16,7 @@ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FakeMediaStreamGraph) public: FakeMediaStreamGraph() - : MediaStreamGraph() + : MediaStreamGraph(16000) { } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControl.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControl.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControl.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControl.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -37,6 +37,7 @@ #include "mozilla/dom/CameraFacesDetectedEvent.h" #include "mozilla/dom/CameraFacesDetectedEventBinding.h" #include "mozilla/dom/CameraStateChangeEvent.h" +#include "mozilla/dom/CameraClosedEvent.h" #include "mozilla/dom/BlobEvent.h" #include "DOMCameraDetectedFace.h" #include "mozilla/dom/BindingUtils.h" @@ -1214,7 +1215,8 @@ // Camera Control event handlers--must only be called from the Main Thread! void -nsDOMCameraControl::OnHardwareStateChange(CameraControlListener::HardwareState aState) +nsDOMCameraControl::OnHardwareStateChange(CameraControlListener::HardwareState aState, + nsresult aReason) { MOZ_ASSERT(NS_IsMainThread()); ErrorResult ignored; @@ -1222,6 +1224,7 @@ switch (aState) { case CameraControlListener::kHardwareOpen: DOM_CAMERA_LOGI("DOM OnHardwareStateChange: open\n"); + MOZ_ASSERT(aReason == NS_OK); { // The hardware is open, so we can return a camera to JS, even if // the preview hasn't started yet. @@ -1245,29 +1248,53 @@ DOM_CAMERA_LOGI("DOM OnHardwareStateChange: closed\n"); { nsRefPtr promise = mReleasePromise.forget(); - if (promise || mReleaseOnSuccessCb) { - // If we have this event handler, this was a solicited hardware close. - if (promise) { - promise->MaybeResolve(JS::UndefinedHandleValue); - } - nsRefPtr cb = mReleaseOnSuccessCb.forget(); - mReleaseOnErrorCb = nullptr; - if (cb) { - cb->Call(ignored); - } - } else { - // If not, something else closed the hardware. - nsRefPtr cb = mOnClosedCb; - if (cb) { - cb->Call(ignored); - } + if (promise) { + promise->MaybeResolve(JS::UndefinedHandleValue); + } + + nsRefPtr rcb = mReleaseOnSuccessCb.forget(); + mReleaseOnErrorCb = nullptr; + if (rcb) { + ErrorResult ignored; + rcb->Call(ignored); } - DispatchTrustedEvent(NS_LITERAL_STRING("close")); + + CameraClosedEventInit eventInit; + switch (aReason) { + case NS_OK: + eventInit.mReason = NS_LITERAL_STRING("HardwareReleased"); + break; + + case NS_ERROR_FAILURE: + eventInit.mReason = NS_LITERAL_STRING("SystemFailure"); + break; + + case NS_ERROR_NOT_AVAILABLE: + eventInit.mReason = NS_LITERAL_STRING("NotAvailable"); + break; + + default: + DOM_CAMERA_LOGE("Unhandled hardware close reason, 0x%x\n", aReason); + MOZ_ASSERT_UNREACHABLE("Unanticipated reason for hardware close"); + eventInit.mReason = NS_LITERAL_STRING("SystemFailure"); + break; + } + + nsRefPtr cb = mOnClosedCb; + if (cb) { + cb->Call(eventInit.mReason, ignored); + } + nsRefPtr event = + CameraClosedEvent::Constructor(this, + NS_LITERAL_STRING("close"), + eventInit); + DispatchTrustedEvent(event); } break; case CameraControlListener::kHardwareOpenFailed: DOM_CAMERA_LOGI("DOM OnHardwareStateChange: open failed\n"); + MOZ_ASSERT(aReason == NS_ERROR_NOT_AVAILABLE); OnUserError(DOMCameraControlListener::kInStartCamera, NS_ERROR_NOT_AVAILABLE); break; @@ -1566,8 +1593,24 @@ case CameraControlListener::kInStopCamera: promise = mReleasePromise.forget(); - mReleaseOnSuccessCb = nullptr; errorCb = mReleaseOnErrorCb.forget(); + if (aError == NS_ERROR_NOT_INITIALIZED) { + // This value indicates that the hardware is already closed; which for + // kInStopCamera, is not actually an error. + if (promise) { + promise->MaybeResolve(JS::UndefinedHandleValue); + } + + nsRefPtr cb = mReleaseOnSuccessCb.forget(); + mReleaseOnErrorCb = nullptr; + if (cb) { + ErrorResult ignored; + cb->Call(ignored); + } + + return; + } + mReleaseOnSuccessCb = nullptr; break; case CameraControlListener::kInSetConfiguration: diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControl.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControl.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControl.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControl.h 2014-11-26 21:45:56.000000000 +0000 @@ -187,7 +187,7 @@ void OnTakePictureComplete(nsIDOMBlob* aPicture); void OnFacesDetected(const nsTArray& aFaces); - void OnHardwareStateChange(DOMCameraControlListener::HardwareState aState); + void OnHardwareStateChange(DOMCameraControlListener::HardwareState aState, nsresult aReason); void OnPreviewStateChange(DOMCameraControlListener::PreviewState aState); void OnRecorderStateChange(CameraControlListener::RecorderState aState, int32_t aStatus, int32_t aTrackNum); void OnConfigurationChange(DOMCameraConfiguration* aConfiguration); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControlListener.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControlListener.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControlListener.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControlListener.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -64,28 +64,31 @@ // Specific callback handlers void -DOMCameraControlListener::OnHardwareStateChange(HardwareState aState) +DOMCameraControlListener::OnHardwareStateChange(HardwareState aState, + nsresult aReason) { class Callback : public DOMCallback { public: Callback(nsMainThreadPtrHandle aDOMCameraControl, - HardwareState aState) + HardwareState aState, nsresult aReason) : DOMCallback(aDOMCameraControl) , mState(aState) + , mReason(aReason) { } void RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE { - aDOMCameraControl->OnHardwareStateChange(mState); + aDOMCameraControl->OnHardwareStateChange(mState, mReason); } protected: HardwareState mState; + nsresult mReason; }; - NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState)); + NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState, aReason)); } void diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControlListener.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControlListener.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/DOMCameraControlListener.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/DOMCameraControlListener.h 2014-11-26 21:45:56.000000000 +0000 @@ -23,7 +23,7 @@ virtual void OnFacesDetected(const nsTArray& aFaces) MOZ_OVERRIDE; virtual void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) MOZ_OVERRIDE; - virtual void OnHardwareStateChange(HardwareState aState) MOZ_OVERRIDE; + virtual void OnHardwareStateChange(HardwareState aState, nsresult aReason) MOZ_OVERRIDE; virtual void OnPreviewStateChange(PreviewState aState) MOZ_OVERRIDE; virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) MOZ_OVERRIDE; virtual void OnConfigurationChange(const CameraListenerConfiguration& aConfiguration) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraControl.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraControl.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraControl.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraControl.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -88,7 +88,8 @@ nsresult rv = StartInternal(aInitialConfig); if (NS_WARN_IF(NS_FAILED(rv))) { - OnHardwareStateChange(CameraControlListener::kHardwareOpenFailed); + OnHardwareStateChange(CameraControlListener::kHardwareOpenFailed, + NS_ERROR_NOT_AVAILABLE); } return rv; } @@ -129,12 +130,12 @@ rv = SetConfigurationInternal(*aInitialConfig); if (NS_WARN_IF(NS_FAILED(rv))) { // The initial configuration failed, close up the hardware - StopImpl(); + StopInternal(); return rv; } } - OnHardwareStateChange(CameraControlListener::kHardwareOpen); + OnHardwareStateChange(CameraControlListener::kHardwareOpen, NS_OK); if (aInitialConfig) { return StartPreviewImpl(); } @@ -314,21 +315,113 @@ } nsresult +nsGonkCameraControl::MaybeAdjustVideoSize() +{ + MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread); + MOZ_ASSERT(mSeparateVideoAndPreviewSizesSupported); + + const Size& preview = mCurrentConfiguration.mPreviewSize; + + // Some camera drivers will ignore our preview size if it's larger + // than the currently set video recording size, so in picture mode, we + // give preview size priority, and bump up the video size just in case. + // This is done on a best-effort basis. + + if (preview.width <= mLastRecorderSize.width && + preview.height <= mLastRecorderSize.height) { + DOM_CAMERA_LOGI("Video size %ux%u is suitable for preview size %ux%u\n", + mLastRecorderSize.width, mLastRecorderSize.height, + preview.width, preview.height); + return NS_OK; + } + + nsTArray sizes; + nsresult rv = Get(CAMERA_PARAM_SUPPORTED_VIDEOSIZES, sizes); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + const uint32_t previewArea = preview.width * preview.height; + uint32_t bestDelta = UINT32_MAX; + bool foundBest = false; + SizeIndex best; + + for (SizeIndex i = 0; i < sizes.Length(); ++i) { + const Size& s = sizes[i]; + if (s.width < preview.width || s.height < preview.height) { + continue; + } + + const uint32_t area = s.width * s.height; + const uint32_t delta = area - previewArea; + if (delta < bestDelta) { + bestDelta = delta; + best = i; + foundBest = true; + } + } + + if (!foundBest) { + // If no candidate was found, the driver will be fine with a video size + // smaller than the chosen preview size. + DOM_CAMERA_LOGI("No video size candidate for preview size %ux%u (0x%x)\n", + preview.width, preview.height, rv); + return NS_OK; + } + + DOM_CAMERA_LOGI("Adjusting video size upwards to %ux%u\n", + sizes[best].width, sizes[best].height); + rv = Set(CAMERA_PARAM_VIDEOSIZE, sizes[best]); + if (NS_FAILED(rv)) { + DOM_CAMERA_LOGW("Failed to adjust video size for preview size %ux%u (0x%x)\n", + preview.width, preview.height, rv); + return rv; + } + + mLastRecorderSize = preview; + return NS_OK; +} + +nsresult nsGonkCameraControl::SetPictureConfiguration(const Configuration& aConfig) { DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__); + MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread); - nsresult rv = SetPreviewSize(aConfig.mPreviewSize); + nsTArray sizes; + nsresult rv = Get(CAMERA_PARAM_SUPPORTED_PREVIEWSIZES, sizes); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + Size preview; + rv = GetSupportedSize(aConfig.mPreviewSize, sizes, preview); + if (NS_FAILED(rv)) { + DOM_CAMERA_LOGE( + "Failed to find a supported preview size, requested size %ux%u (0x%x)", + aConfig.mPreviewSize.width, aConfig.mPreviewSize.height, rv); + return rv; + } + + rv = Set(CAMERA_PARAM_PREVIEWSIZE, preview); + if (NS_FAILED(rv)) { + DOM_CAMERA_LOGE("Failed to set supported preview size %ux%u (0x%x)", + preview.width, preview.height, rv); + return rv; + } + + mCurrentConfiguration.mPreviewSize = preview; + + if (mSeparateVideoAndPreviewSizesSupported) { + MaybeAdjustVideoSize(); + } + mParams.Get(CAMERA_PARAM_PREVIEWFRAMERATE, mPreviewFps); DOM_CAMERA_LOGI("picture mode preview: wanted %ux%u, got %ux%u (%u fps)\n", - aConfig.mPreviewSize.width, aConfig.mPreviewSize.height, - mCurrentConfiguration.mPreviewSize.width, mCurrentConfiguration.mPreviewSize.height, - mPreviewFps); + aConfig.mPreviewSize.width, aConfig.mPreviewSize.height, + preview.width, preview.height, + mPreviewFps); return NS_OK; } @@ -695,11 +788,10 @@ int area = supportedSizes[i].width * supportedSizes[i].height; int delta = abs(area - targetArea); - if (area != 0 - && delta < smallestDelta - && supportedSizes[i].width * mLastPictureSize.height / - supportedSizes[i].height == mLastPictureSize.width - ) { + if (area != 0 && + delta < smallestDelta && + supportedSizes[i].width * mLastPictureSize.height == + mLastPictureSize.width * supportedSizes[i].height) { smallestDelta = delta; smallestDeltaIndex = i; } @@ -1062,7 +1154,9 @@ ReentrantMonitorAutoEnter mon(mRecorderMonitor); // nothing to do if we have no mRecorder - NS_ENSURE_TRUE(mRecorder, NS_OK); + if (!mRecorder) { + return NS_OK; + } mRecorder->stop(); mRecorder = nullptr; @@ -1250,70 +1344,8 @@ } nsresult -nsGonkCameraControl::SetPreviewSize(const Size& aSize) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread); - - nsTArray previewSizes; - nsresult rv = Get(CAMERA_PARAM_SUPPORTED_PREVIEWSIZES, previewSizes); - if (NS_FAILED(rv)) { - DOM_CAMERA_LOGE("Camera failed to return any preview sizes (0x%x)\n", rv); - return rv; - } - - Size best; - rv = GetSupportedSize(aSize, previewSizes, best); - if (NS_FAILED(rv)) { - DOM_CAMERA_LOGE("Failed to find a supported preview size, requested size %dx%d", - aSize.width, aSize.height); - return rv; - } - - if (mSeparateVideoAndPreviewSizesSupported) { - // Some camera drivers will ignore our preview size if it's larger - // than the currently set video recording size, so we need to set - // the video size here as well, just in case. - if (best.width > mLastRecorderSize.width || best.height > mLastRecorderSize.height) { - SetVideoSize(best); - } - } else { - mLastRecorderSize = best; - } - mCurrentConfiguration.mPreviewSize = best; - return Set(CAMERA_PARAM_PREVIEWSIZE, best); -} - -nsresult -nsGonkCameraControl::SetVideoSize(const Size& aSize) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread); - - if (!mSeparateVideoAndPreviewSizesSupported) { - DOM_CAMERA_LOGE("Camera does not support setting separate video size\n"); - return NS_ERROR_NOT_AVAILABLE; - } - - nsTArray videoSizes; - nsresult rv = Get(CAMERA_PARAM_SUPPORTED_VIDEOSIZES, videoSizes); - if (NS_FAILED(rv)) { - DOM_CAMERA_LOGE("Camera failed to return any video sizes (0x%x)\n", rv); - return rv; - } - - Size best; - rv = GetSupportedSize(aSize, videoSizes, best); - if (NS_FAILED(rv)) { - DOM_CAMERA_LOGE("Failed to find a supported video size, requested size %dx%d", - aSize.width, aSize.height); - return rv; - } - mLastRecorderSize = best; - return Set(CAMERA_PARAM_VIDEOSIZE, best); -} - -nsresult nsGonkCameraControl::GetSupportedSize(const Size& aSize, - const nsTArray& supportedSizes, + const nsTArray& aSupportedSizes, Size& best) { nsresult rv = NS_ERROR_INVALID_ARG; @@ -1323,24 +1355,25 @@ if (!aSize.width && !aSize.height) { // no size specified, take the first supported size - best = supportedSizes[0]; + best = aSupportedSizes[0]; return NS_OK; } else if (aSize.width && aSize.height) { // both height and width specified, find the supported size closest to // the requested size, looking for an exact match first - for (nsTArray::index_type i = 0; i < supportedSizes.Length(); i++) { - Size size = supportedSizes[i]; + for (SizeIndex i = 0; i < aSupportedSizes.Length(); ++i) { + Size size = aSupportedSizes[i]; if (size.width == aSize.width && size.height == aSize.height) { best = size; return NS_OK; } } - // no exact matches--look for a match closest in area - uint32_t targetArea = aSize.width * aSize.height; - for (nsTArray::index_type i = 0; i < supportedSizes.Length(); i++) { - Size size = supportedSizes[i]; - uint32_t delta = abs((long int)(size.width * size.height - targetArea)); + // no exact match on dimensions--look for a match closest in area + const uint32_t targetArea = aSize.width * aSize.height; + for (SizeIndex i = 0; i < aSupportedSizes.Length(); i++) { + Size size = aSupportedSizes[i]; + uint32_t delta = + abs(static_cast(size.width * size.height - targetArea)); if (delta < minSizeDelta) { minSizeDelta = delta; best = size; @@ -1349,9 +1382,9 @@ } } else if (!aSize.width) { // width not specified, find closest height match - for (nsTArray::index_type i = 0; i < supportedSizes.Length(); i++) { - Size size = supportedSizes[i]; - delta = abs((long int)(size.height - aSize.height)); + for (SizeIndex i = 0; i < aSupportedSizes.Length(); i++) { + Size size = aSupportedSizes[i]; + delta = abs(static_cast(size.height - aSize.height)); if (delta < minSizeDelta) { minSizeDelta = delta; best = size; @@ -1360,9 +1393,9 @@ } } else if (!aSize.height) { // height not specified, find closest width match - for (nsTArray::index_type i = 0; i < supportedSizes.Length(); i++) { - Size size = supportedSizes[i]; - delta = abs((long int)(size.width - aSize.width)); + for (SizeIndex i = 0; i < aSupportedSizes.Length(); i++) { + Size size = aSupportedSizes[i]; + delta = abs(static_cast(size.width - aSize.width)); if (delta < minSizeDelta) { minSizeDelta = delta; best = size; @@ -1370,10 +1403,148 @@ } } } + return rv; } nsresult +nsGonkCameraControl::SetVideoAndPreviewSize(const Size& aPreviewSize, const Size& aVideoSize) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread); + MOZ_ASSERT(mSeparateVideoAndPreviewSizesSupported); + + DOM_CAMERA_LOGI("Setting video size to %ux%u, preview size to %ux%u\n", + aVideoSize.width, aVideoSize.height, + aPreviewSize.width, aPreviewSize.height); + + Size oldSize; + nsresult rv = Get(CAMERA_PARAM_PREVIEWSIZE, oldSize); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = Set(CAMERA_PARAM_PREVIEWSIZE, aPreviewSize); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + rv = Set(CAMERA_PARAM_VIDEOSIZE, aVideoSize); + if (NS_WARN_IF(NS_FAILED(rv))) { + Set(CAMERA_PARAM_VIDEOSIZE, oldSize); // error, try to restore the original preview size + return rv; + } + + mCurrentConfiguration.mPreviewSize = aPreviewSize; + mLastRecorderSize = aVideoSize; + + return NS_OK; +} + +nsresult +nsGonkCameraControl::SelectVideoAndPreviewSize(const Configuration& aConfig, const Size& aVideoSize) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread); + MOZ_ASSERT(mSeparateVideoAndPreviewSizesSupported); + + nsTArray sizes; + + nsresult rv = Get(CAMERA_PARAM_SUPPORTED_VIDEOSIZES, sizes); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + Size video; + rv = GetSupportedSize(aVideoSize, sizes, video); + if (NS_FAILED(rv)) { + DOM_CAMERA_LOGE("Failed to find a supported video size, requested size %ux%u", + aVideoSize.width, aVideoSize.height); + return rv; + } + + rv = Get(CAMERA_PARAM_SUPPORTED_PREVIEWSIZES, sizes); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + Size preview; + rv = GetSupportedSize(aConfig.mPreviewSize, sizes, preview); + if (NS_FAILED(rv)) { + DOM_CAMERA_LOGE("Failed to find a supported preview size, requested size %ux%u", + aConfig.mPreviewSize.width, aConfig.mPreviewSize.height); + return rv; + } + + Size preferred; + rv = Get(CAMERA_PARAM_PREFERRED_PREVIEWSIZE_FOR_VIDEO, preferred); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // If the requested preview size has the same aspect ratio as the + // requested video size, *and* is the same size or smaller than + // the preferred video size, then we're done. + const uint32_t preferredArea = preferred.width * preferred.height; + if (video.width * aConfig.mPreviewSize.height == aConfig.mPreviewSize.width * video.height && + preview.width * preview.height <= preferredArea) { + // We're done: set the video and preview sizes and return... + return SetVideoAndPreviewSize(preview, video); + } + + // Otherwise, if the requested preview size is larger than the preferred + // size, or there is an aspect ratio mismatch, then we need to set the + // preview size to the closest size smaller than the preferred size, + // preferably with the same aspect ratio as the requested video size. + + SizeIndex bestSizeMatch = 0; // initializers to keep warnings away + SizeIndex bestSizeMatchWithAspectRatio = 0; + bool foundSizeMatch = false; + bool foundSizeMatchWithAspectRatio = false; + + uint32_t bestAreaDelta = UINT32_MAX; + uint32_t bestAreaDeltaWithAspect = UINT32_MAX; + + for (SizeIndex i = 0; i < sizes.Length(); ++i) { + const Size& s = sizes[i]; + const uint32_t area = s.width * s.height; + if (area > preferredArea) { + continue; + } + + const uint32_t delta = preferredArea - area; + if (s.width * video.height == video.width * s.height) { + if (delta == 0) { + // exact match, including aspect ratio--we can stop now + bestSizeMatchWithAspectRatio = i; + foundSizeMatchWithAspectRatio = true; + break; + } else if (delta < bestAreaDeltaWithAspect) { + // aspect ratio match + bestAreaDeltaWithAspect = delta; + bestSizeMatchWithAspectRatio = i; + foundSizeMatchWithAspectRatio = true; + } + } else if (delta < bestAreaDelta) { + bestAreaDelta = delta; + bestSizeMatch = i; + foundSizeMatch = true; + } + } + + if (foundSizeMatchWithAspectRatio) { + preview = sizes[bestSizeMatchWithAspectRatio]; + } else if (foundSizeMatch) { + DOM_CAMERA_LOGW("Unable to match a preview size with aspect ratio of video size %ux%u\n", + video.width, video.height); + preview = sizes[bestSizeMatch]; + } else { + DOM_CAMERA_LOGE("Unable to find a preview size for video size %ux%u\n", + video.width, video.height); + return NS_ERROR_INVALID_ARG; + } + + return SetVideoAndPreviewSize(preview, video); +} + +nsresult nsGonkCameraControl::SetVideoConfiguration(const Configuration& aConfig) { DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__); @@ -1392,12 +1563,11 @@ return NS_ERROR_INVALID_ARG; } - mCurrentConfiguration.mRecorderProfile = aConfig.mRecorderProfile; const RecorderProfile::Video& video(profile->GetVideo()); const Size& size = video.GetSize(); - int fps = video.GetFramesPerSecond(); - if (fps <= 0 || size.width <= 0 || size.height <= 0) { - DOM_CAMERA_LOGE("Can't configure video with fps=%d, width=%d, height=%d\n", + const uint32_t fps = video.GetFramesPerSecond(); + if (fps == 0 || fps > INT_MAX || size.width == 0 || size.height == 0) { + DOM_CAMERA_LOGE("Can't configure video with fps=%u, width=%u, height=%u\n", fps, size.width, size.height); return NS_ERROR_FAILURE; } @@ -1410,32 +1580,26 @@ if (mSeparateVideoAndPreviewSizesSupported) { // The camera supports two video streams: a low(er) resolution preview - // stream and and a potentially high(er) resolution stream for encoding. - rv = SetVideoSize(size); - if (NS_FAILED(rv)) { - DOM_CAMERA_LOGE("Failed to set video mode video size (0x%x)\n", rv); - return rv; - } - - // The video size must be set first, before the preview size, because - // some platforms have a dependency between the two. - rv = SetPreviewSize(aConfig.mPreviewSize); + // stream and and a potentially high(er) resolution stream for encoding. + rv = SelectVideoAndPreviewSize(aConfig, size); if (NS_FAILED(rv)) { - DOM_CAMERA_LOGE("Failed to set video mode preview size (0x%x)\n", rv); + DOM_CAMERA_LOGE("Failed to set video and preview sizes (0x%x)\n", rv); return rv; } } else { // The camera only supports a single video stream: in this case, we set // the preview size to be the desired video recording size, and ignore // the specified preview size. - rv = SetPreviewSize(size); + rv = Set(CAMERA_PARAM_PREVIEWSIZE, size); if (NS_FAILED(rv)) { DOM_CAMERA_LOGE("Failed to set video mode preview size (0x%x)\n", rv); return rv; } + + mCurrentConfiguration.mPreviewSize = size; } - rv = Set(CAMERA_PARAM_PREVIEWFRAMERATE, fps); + rv = Set(CAMERA_PARAM_PREVIEWFRAMERATE, static_cast(fps)); if (NS_FAILED(rv)) { DOM_CAMERA_LOGE("Failed to set video mode frame rate (0x%x)\n", rv); return rv; @@ -1665,7 +1829,7 @@ } nsresult -nsGonkCameraControl::StopImpl() +nsGonkCameraControl::StopInternal() { DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); @@ -1673,7 +1837,7 @@ StopRecordingImpl(); // stop the preview - StopPreviewImpl(); + nsresult rv = StopPreviewImpl(); // release the hardware handle if (mCameraHw.get()){ @@ -1681,8 +1845,22 @@ mCameraHw.clear(); } - OnHardwareStateChange(CameraControlListener::kHardwareClosed); - return NS_OK; + return rv; +} + +nsresult +nsGonkCameraControl::StopImpl() +{ + DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); + + nsresult rv = StopInternal(); + if (rv != NS_ERROR_NOT_INITIALIZED) { + rv = NS_OK; + } + if (NS_SUCCEEDED(rv)) { + OnHardwareStateChange(CameraControlListener::kHardwareClosed, NS_OK); + } + return rv; } nsresult @@ -1785,8 +1963,8 @@ nsresult aError) { if (aWhere == CameraControlListener::kSystemService) { - OnPreviewStateChange(CameraControlListener::kPreviewStopped); - OnHardwareStateChange(CameraControlListener::kHardwareClosed); + StopInternal(); + OnHardwareStateChange(CameraControlListener::kHardwareClosed, NS_ERROR_FAILURE); } CameraControlImpl::OnSystemError(aWhere, aError); @@ -1844,12 +2022,6 @@ } void -OnClosed(nsGonkCameraControl* gc) -{ - gc->OnClosed(); -} - -void OnSystemError(nsGonkCameraControl* gc, CameraControlListener::SystemContext aWhere, int32_t aArg1, int32_t aArg2) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraControl.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraControl.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraControl.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraControl.h 2014-11-26 21:45:56.000000000 +0000 @@ -98,6 +98,8 @@ using CameraControlImpl::OnConfigurationChange; using CameraControlImpl::OnUserError; + typedef nsTArray::index_type SizeIndex; + virtual void BeginBatchParameterSet() MOZ_OVERRIDE; virtual void EndBatchParameterSet() MOZ_OVERRIDE; @@ -107,6 +109,7 @@ nsresult SetPictureConfiguration(const Configuration& aConfig); nsresult SetVideoConfiguration(const Configuration& aConfig); nsresult StartInternal(const Configuration* aInitialConfig); + nsresult StopInternal(); template nsresult SetAndPush(uint32_t aKey, const T& aValue); @@ -130,8 +133,9 @@ nsresult SetupRecording(int aFd, int aRotation, uint64_t aMaxFileSizeBytes, uint64_t aMaxVideoLengthMs); nsresult SetupRecordingFlash(bool aAutoEnableLowLightTorch); - nsresult SetPreviewSize(const Size& aSize); - nsresult SetVideoSize(const Size& aSize); + nsresult SelectVideoAndPreviewSize(const Configuration& aConfig, const Size& aVideoSize); + nsresult SetVideoAndPreviewSize(const Size& aPreviewSize, const Size& aVideoSize); + nsresult MaybeAdjustVideoSize(); nsresult PausePreview(); nsresult GetSupportedSize(const Size& aSize, const nsTArray& supportedSizes, Size& best); @@ -195,7 +199,6 @@ void OnFacesDetected(nsGonkCameraControl* gc, camera_frame_metadata_t* aMetaData); void OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer); void OnShutter(nsGonkCameraControl* gc); -void OnClosed(nsGonkCameraControl* gc); void OnSystemError(nsGonkCameraControl* gc, CameraControlListener::SystemContext aWhere, int32_t aArg1, int32_t aArg2); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraHwMgr.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraHwMgr.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraHwMgr.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraHwMgr.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -268,18 +268,6 @@ DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, (void*)this); mCamera.clear(); mNativeWindow.clear(); - - if (mClosing) { - return; - } - - /** - * Trigger the OnClosed event; the upper layers can't do anything - * with the hardware layer once they receive this event. - */ - if (mTarget) { - OnClosed(mTarget); - } } int diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraParameters.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraParameters.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/GonkCameraParameters.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/GonkCameraParameters.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -117,6 +117,8 @@ return KEY_RECORDING_HINT; case CAMERA_PARAM_PICTURE_QUALITY: return KEY_JPEG_QUALITY; + case CAMERA_PARAM_PREFERRED_PREVIEWSIZE_FOR_VIDEO: + return KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO; case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES: return KEY_SUPPORTED_PREVIEW_SIZES; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/ICameraControl.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/ICameraControl.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/ICameraControl.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/ICameraControl.h 2014-11-26 21:45:56.000000000 +0000 @@ -54,6 +54,7 @@ CAMERA_PARAM_LUMINANCE, CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE, CAMERA_PARAM_RECORDINGHINT, + CAMERA_PARAM_PREFERRED_PREVIEWSIZE_FOR_VIDEO, // supported features CAMERA_PARAM_SUPPORTED_PREVIEWSIZES, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/callback/test_bug1099390.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/callback/test_bug1099390.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/callback/test_bug1099390.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/callback/test_bug1099390.html 2014-11-26 21:45:57.000000000 +0000 @@ -0,0 +1,107 @@ + + + + Test for bug 1099390 + + + + + + + +This image is going to load + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/callback/test_camera_hardware_init_failure.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/callback/test_camera_hardware_init_failure.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/callback/test_camera_hardware_init_failure.html 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/callback/test_camera_hardware_init_failure.html 2014-11-26 21:45:57.000000000 +0000 @@ -65,11 +65,64 @@ info("Running test: init-success"); navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError) } - } + }, + /* Test for bug 1099390 to make sure events related to the underlying + platform failing are generated and handled properly. */ + { + name: "post-init-system-failure", + key: "post-init-system-failure", + func: function(test) { + var gotReleaseCallback = false; + var gotCloseCallback = false; + + function gotAll() { + var all = gotReleaseCallback && gotCloseCallback; + if (all) { + info("Got all expected notifications"); + } + return all; + } + + function onSuccess(camera, config) { + camera.onClosed = function(reason) { + camera.onClosed = null; + ok(reason === "SystemFailure", "reason is: " + reason); + ok(!gotCloseCallback, "gotCloseCallback was " + gotCloseCallback); + gotCloseCallback = true; + if (gotAll()) { + test.next(); + } + + camera.release( + function success() { + ok(true, "Got release() success callback"); + ok(!gotReleaseCallback, "gotReleaseCallback was " + gotReleaseCallback); + gotReleaseCallback = true; + if (gotAll()) { + test.next(); + } + }, + function error(e) { + ok(false, "Unexpected release() onError callback: " + e); + test.next(); + } + ); // release() + } // onClosed + } // onSuccess + + function onError(error) { + ok(false, "onError called incorrectly: " + error); + test.next(); + } + + info("Running test: post-init-system-failure"); + navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError); + } + }, ]; var testGenerator = function() { - for (var i = 0; i < tests.length; ++i ) { + for (var i = 0; i < tests.length; ++i) { yield tests[i]; } }(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/mochitest.ini 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/mochitest.ini 2014-11-26 21:45:57.000000000 +0000 @@ -10,6 +10,7 @@ [callback/test_camera_hardware_face_detection.html] [callback/test_camera_hardware_auto_focus_moving_cb.html] [callback/test_bug1022766.html] +[callback/test_bug1099390.html] [test_camera.html] [test_camera_2.html] [test_camera_3.html] @@ -21,3 +22,4 @@ [test_camera_hardware_auto_focus_moving_cb.html] [test_bug1022766.html] [test_bug1037322.html] +[test_bug1099390.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/test_bug1099390.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/test_bug1099390.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/test_bug1099390.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/test_bug1099390.html 2014-11-26 21:45:57.000000000 +0000 @@ -0,0 +1,108 @@ + + + + Test for bug 1099390 + + + + + + + +This image is going to load + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/test_camera_hardware_init_failure.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/test_camera_hardware_init_failure.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/test/test_camera_hardware_init_failure.html 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/test/test_camera_hardware_init_failure.html 2014-11-26 21:45:57.000000000 +0000 @@ -55,8 +55,7 @@ func: function(test) { function onSuccess(d) { ok(true, "onSuccess called correctly"); - d.camera.release(); - test.next(); + d.camera.release().then(test.next); } function onError(error) { ok(false, "onError called incorrectly: " + error); @@ -65,11 +64,66 @@ info("Running test: init-success"); navigator.mozCameras.getCamera(whichCamera, initialConfig).then(onSuccess, onError) } - } + }, + /* Test for bug 1099390 to make sure events related to the underlying + platform failing are generated and handled properly. */ + { + name: "post-init-system-failure", + key: "post-init-system-failure", + func: function(test) { + var gotReleasePromise = false; + var gotCloseEvent = false; + + function gotAll() { + var all = gotReleasePromise && gotCloseEvent; + if (all) { + info("Got all expected notifications"); + } + return all; + } + + function onSuccess(d) { + var onClosedEvent = function(e) { + d.camera.removeEventListener('close', onClosedEvent); + + ok(e.reason === "SystemFailure", "reason is: " + e.reason); + ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent); + gotCloseEvent = true; + if (gotAll()) { + test.next(); + } + + d.camera.release().then( + function resolve(e) { + ok(true, "release() promise resolved"); + ok(!gotReleasePromise, "gotReleasePromise was " + gotReleasePromise); + gotReleasePromise = true; + if (gotAll()) { + test.next(); + } + }, + function reject(e) { + ok(false, "release() promise unexpected rejected: " + e); + } + ); + }; + + d.camera.addEventListener('close', onClosedEvent); + } + + function onError(error) { + ok(false, "onError called incorrectly: " + error); + test.next(); + } + + info("Running test: post-init-system-failure"); + navigator.mozCameras.getCamera(whichCamera, initialConfig).then(onSuccess, onError) + } + }, ]; var testGenerator = function() { - for (var i = 0; i < tests.length; ++i ) { + for (var i = 0; i < tests.length; ++i) { yield tests[i]; } }(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/TestGonkCameraHardware.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/TestGonkCameraHardware.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/TestGonkCameraHardware.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/TestGonkCameraHardware.cpp 2014-11-26 21:45:56.000000000 +0000 @@ -39,12 +39,45 @@ DOM_CAMERA_LOGA("^===== Destroyed TestGonkCameraHardware =====^\n"); } +void +TestGonkCameraHardware::InjectFakeSystemFailure() +{ + DOM_CAMERA_LOGA("====== Fake Camera Hardware Failure ======\n"); + // The values '100' and '0' below seem to be what the AOSP layer + // throws back when the mediaserver process fails. + OnSystemError(mTarget, CameraControlListener::kSystemService, 100, 0); +} + nsresult TestGonkCameraHardware::Init() { + class DeferredSystemFailure : public nsRunnable + { + public: + DeferredSystemFailure(TestGonkCameraHardware* aCameraHw) + : mCameraHw(aCameraHw) + { } + + NS_IMETHODIMP + Run() + { + mCameraHw->InjectFakeSystemFailure(); + return NS_OK; + } + + protected: + android::sp mCameraHw; + }; + if (IsTestCase("init-failure")) { return NS_ERROR_NOT_INITIALIZED; } + if (IsTestCase("post-init-system-failure")) { + nsCOMPtr me = NS_GetCurrentThread(); + if (me) { + me->Dispatch(new DeferredSystemFailure(this), NS_DISPATCH_NORMAL); + } + } return GonkCameraHardware::Init(); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/TestGonkCameraHardware.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/TestGonkCameraHardware.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/camera/TestGonkCameraHardware.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/camera/TestGonkCameraHardware.h 2014-11-26 21:45:56.000000000 +0000 @@ -62,6 +62,7 @@ int TestCaseError(int aDefaultError); int StartAutoFocusMoving(bool aIsMoving); + void InjectFakeSystemFailure(); private: TestGonkCameraHardware(const TestGonkCameraHardware&) MOZ_DELETE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/CanvasRenderingContext2D.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/CanvasRenderingContext2D.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/CanvasRenderingContext2D.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/CanvasRenderingContext2D.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -89,6 +89,7 @@ #include "mozilla/MathAlgorithms.h" #include "mozilla/Preferences.h" #include "mozilla/Telemetry.h" +#include "mozilla/TimeStamp.h" #include "mozilla/UniquePtr.h" #include "mozilla/unused.h" #include "nsCCUncollectableMarker.h" @@ -691,6 +692,106 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasPattern, mContext) +class CanvasDrawObserver +{ +public: + CanvasDrawObserver(CanvasRenderingContext2D* aCanvasContext); + + // Only enumerate draw calls that could affect the heuristic + enum DrawCallType { + PutImageData, + GetImageData, + DrawImage + }; + + // This is the one that we call on relevant draw calls and count + // GPU vs. CPU preferrable calls... + void DidDrawCall(DrawCallType aType); + + // When this returns true, the observer is done making the decisions. + // Right now, we expect to get rid of the observer after the FrameEnd + // returns true, though the decision could eventually change if the + // function calls shift. If we change to monitor the functions called + // and make decisions to change more than once, we would probably want + // FrameEnd to reset the timer and counters as it returns true. + bool FrameEnd(); + +private: + // These values will be picked up from preferences: + int32_t mMinFramesBeforeDecision; + float mMinSecondsBeforeDecision; + int32_t mMinCallsBeforeDecision; + + CanvasRenderingContext2D* mCanvasContext; + int32_t mSoftwarePreferredCalls; + int32_t mGPUPreferredCalls; + int32_t mFramesRendered; + TimeStamp mCreationTime; +}; + +// We are not checking for the validity of the preference values. For example, +// negative values will have an effect of a quick exit, so no harm done. +CanvasDrawObserver::CanvasDrawObserver(CanvasRenderingContext2D* aCanvasContext) + : mMinFramesBeforeDecision(gfxPrefs::CanvasAutoAccelerateMinFrames()) + , mMinSecondsBeforeDecision(gfxPrefs::CanvasAutoAccelerateMinSeconds()) + , mMinCallsBeforeDecision(gfxPrefs::CanvasAutoAccelerateMinCalls()) + , mCanvasContext(aCanvasContext) + , mSoftwarePreferredCalls(0) + , mGPUPreferredCalls(0) + , mFramesRendered(0) + , mCreationTime(TimeStamp::NowLoRes()) +{} + +void +CanvasDrawObserver::DidDrawCall(DrawCallType aType) +{ + switch (aType) { + case PutImageData: + case GetImageData: + if (mGPUPreferredCalls == 0 && mSoftwarePreferredCalls == 0) { + mCreationTime = TimeStamp::NowLoRes(); + } + mSoftwarePreferredCalls++; + break; + case DrawImage: + if (mGPUPreferredCalls == 0 && mSoftwarePreferredCalls == 0) { + mCreationTime = TimeStamp::NowLoRes(); + } + mGPUPreferredCalls++; + break; + } +} + +// If we return true, the observer is done making the decisions... +bool +CanvasDrawObserver::FrameEnd() +{ + mFramesRendered++; + + // We log the first mMinFramesBeforeDecision frames of any + // canvas object then make a call to determine whether it should + // be GPU or CPU backed + if ((mFramesRendered >= mMinFramesBeforeDecision) || + ((TimeStamp::NowLoRes() - mCreationTime).ToSeconds()) > mMinSecondsBeforeDecision) { + + // If we don't have enough data, don't bother changing... + if (mGPUPreferredCalls > mMinCallsBeforeDecision || + mSoftwarePreferredCalls > mMinCallsBeforeDecision) { + if (mGPUPreferredCalls >= mSoftwarePreferredCalls) { + mCanvasContext->SwitchRenderingMode(CanvasRenderingContext2D::RenderingMode::OpenGLBackendMode); + } else { + mCanvasContext->SwitchRenderingMode(CanvasRenderingContext2D::RenderingMode::SoftwareBackendMode); + } + } + + // If we ever redesign this class to constantly monitor the functions + // and keep making decisions, we would probably want to reset the counters + // and the timers here... + return true; + } + return false; +} + class CanvasRenderingContext2DUserData : public LayerUserData { public: explicit CanvasRenderingContext2DUserData(CanvasRenderingContext2D *aContext) @@ -724,6 +825,12 @@ static_cast(aData); if (self->mContext) { self->mContext->MarkContextClean(); + if (self->mContext->mDrawObserver) { + if (self->mContext->mDrawObserver->FrameEnd()) { + // Note that this call deletes and nulls out mDrawObserver: + self->mContext->RemoveDrawObserver(); + } + } } } bool IsForContext(CanvasRenderingContext2D *aContext) @@ -828,6 +935,7 @@ , mZero(false), mOpaque(false) , mResetLayer(true) , mIPC(false) + , mDrawObserver(nullptr) , mIsEntireFrameInvalid(false) , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false) , mInvalidateCount(0) @@ -839,10 +947,14 @@ mRenderingMode = RenderingMode::SoftwareBackendMode; } + if (gfxPlatform::GetPlatform()->HaveChoiceOfHWAndSWCanvas()) { + mDrawObserver = new CanvasDrawObserver(this); + } } CanvasRenderingContext2D::~CanvasRenderingContext2D() { + RemoveDrawObserver(); RemovePostRefreshObserver(); Reset(); // Drop references from all CanvasRenderingContext2DUserData to this context @@ -1443,6 +1555,10 @@ if (Preferences::GetBool("gfx.canvas.willReadFrequently.enable", false)) { // Use software when there is going to be a lot of readback if (attributes.mWillReadFrequently) { + + // We want to lock into software, so remove the observer that + // may potentially change that... + RemoveDrawObserver(); mRenderingMode = RenderingMode::SoftwareBackendMode; } } @@ -1619,6 +1735,12 @@ mTarget->SetTransform(matrix); } +void +CanvasRenderingContext2D::ResetTransform(ErrorResult& error) +{ + SetTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, error); +} + static void MatrixToJSObject(JSContext* cx, const Matrix& matrix, JS::MutableHandle result, ErrorResult& error) @@ -3131,7 +3253,7 @@ mFontgrp->UpdateUserFonts(); // ensure user font generation is current // adjust flags for current direction run uint32_t flags = mTextRunFlags; - if (direction & 1) { + if (direction == NSBIDI_RTL) { flags |= gfxTextRunFactory::TEXT_IS_RTL; } else { flags &= ~gfxTextRunFactory::TEXT_IS_RTL; @@ -3578,8 +3700,13 @@ MOZ_CRASH("unexpected TextBaseline"); } - if (processor.mTextRun->IsVertical()) { - if (processor.mTextRun->UseCenterBaseline()) { + // We can't query the textRun directly, as it may not have been created yet; + // so instead we check the flags that will be used to initialize it. + uint16_t runOrientation = + (processor.mTextRunFlags & gfxTextRunFactory::TEXT_ORIENT_MASK); + if (runOrientation != gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL) { + if (runOrientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED || + runOrientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT) { // Adjust to account for mTextRun being shaped using center baseline // rather than alphabetic. baselineAnchor -= (fontMetrics.emAscent - fontMetrics.emDescent) * .5f; @@ -4009,6 +4136,10 @@ uint8_t optional_argc, ErrorResult& error) { + if (mDrawObserver) { + mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::DrawImage); + } + MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6); RefPtr srcSurf; @@ -4628,6 +4759,10 @@ double aSy, double aSw, double aSh, ErrorResult& error) { + if (mDrawObserver) { + mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::GetImageData); + } + EnsureTarget(); if (!IsTargetValid()) { error.Throw(NS_ERROR_FAILURE); @@ -4708,6 +4843,10 @@ uint32_t aHeight, JSObject** aRetval) { + if (mDrawObserver) { + mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::GetImageData); + } + MOZ_ASSERT(aWidth && aHeight); CheckedInt len = CheckedInt(aWidth) * aHeight * 4; @@ -4887,6 +5026,10 @@ bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY, int32_t dirtyWidth, int32_t dirtyHeight) { + if (mDrawObserver) { + mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::PutImageData); + } + if (w == 0 || h == 0) { return NS_ERROR_DOM_INVALID_STATE_ERR; } @@ -5066,6 +5209,15 @@ return (uint32_t)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE); } +void CanvasRenderingContext2D::RemoveDrawObserver() +{ + if (mDrawObserver) { + delete mDrawObserver; + mDrawObserver = nullptr; + } +} + + already_AddRefed CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder, CanvasLayer *aOldLayer, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/CanvasRenderingContext2D.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/CanvasRenderingContext2D.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/CanvasRenderingContext2D.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/CanvasRenderingContext2D.h 2014-11-26 21:45:57.000000000 +0000 @@ -114,6 +114,7 @@ struct CanvasBidiProcessor; class CanvasRenderingContext2DUserData; +class CanvasDrawObserver; /** ** CanvasRenderingContext2D @@ -147,6 +148,7 @@ double dy, mozilla::ErrorResult& error); void SetTransform(double m11, double m12, double m21, double m22, double dx, double dy, mozilla::ErrorResult& error); + void ResetTransform(mozilla::ErrorResult& error); double GlobalAlpha() { @@ -775,6 +777,12 @@ uint32_t SkiaGLTex() const; + // This observes our draw calls at the beginning of the canvas + // lifetime and switches to software or GPU mode depending on + // what it thinks is best + CanvasDrawObserver* mDrawObserver; + void RemoveDrawObserver(); + /** * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever * Redraw is called, reset to false when Render is called. @@ -1089,6 +1097,7 @@ } friend struct CanvasBidiProcessor; + friend class CanvasDrawObserver; }; MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/crashtests/1099143-1.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/crashtests/1099143-1.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/crashtests/1099143-1.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/crashtests/1099143-1.html 2014-11-26 21:45:57.000000000 +0000 @@ -0,0 +1,5 @@ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/crashtests/crashtests.list thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/crashtests/crashtests.list --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/crashtests/crashtests.list 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/crashtests/crashtests.list 2014-11-26 21:45:57.000000000 +0000 @@ -21,3 +21,4 @@ load 896047-2.html load 916128-1.html load 934939-1.html +load 1099143-1.html diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/moz.build 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/moz.build 2014-11-26 21:45:57.000000000 +0000 @@ -55,7 +55,6 @@ 'WebGLActiveInfo.cpp', 'WebGLBuffer.cpp', 'WebGLContext.cpp', - 'WebGLContextAsyncQueries.cpp', 'WebGLContextBuffers.cpp', 'WebGLContextDraw.cpp', 'WebGLContextExtensions.cpp', @@ -64,6 +63,7 @@ 'WebGLContextLossHandler.cpp', 'WebGLContextReporter.cpp', 'WebGLContextState.cpp', + 'WebGLContextUnchecked.cpp', 'WebGLContextUtils.cpp', 'WebGLContextValidate.cpp', 'WebGLContextVertexArray.cpp', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/test/test_canvas.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/test/test_canvas.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/test/test_canvas.html 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/test/test_canvas.html 2014-11-26 21:45:57.000000000 +0000 @@ -19182,6 +19182,7 @@ } + @@ -19558,6 +19559,9 @@ if (ctx.setTransform) { ok(ctx.setTransform(1, 0, 0, 1, 0, 0) === undefined, "ctx.setTransform(1, 0, 0, 1, 0, 0) === undefined"); } +if (ctx.resetTransform) { + ok(ctx.resetTransform() === undefined, "ctx.resetTransform() === undefined"); +} ok(ctx.clearRect(0, 0, 0, 0) === undefined, "ctx.clearRect(0, 0, 0, 0) === undefined"); ok(ctx.fillRect(0, 0, 0, 0) === undefined, "ctx.fillRect(0, 0, 0, 0) === undefined"); ok(ctx.strokeRect(0, 0, 0, 0) === undefined, "ctx.strokeRect(0, 0, 0, 0) === undefined"); @@ -21552,6 +21556,31 @@ } +

Canvas test: 2d.transformation.transform.identity

+ +

FAIL (fallback content)

+ + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/test/webgl-mochitest/test_webgl_request_mismatch.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/test/webgl-mochitest/test_webgl_request_mismatch.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/test/webgl-mochitest/test_webgl_request_mismatch.html 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/test/webgl-mochitest/test_webgl_request_mismatch.html 2014-11-26 21:45:57.000000000 +0000 @@ -1,35 +1,90 @@ -WebGL test: Mismatched 'webgl' and 'experimental-webgl' context requests + + + - - - - +function AreBothIn(a, b, set) { + return (a in set) && (b in set); +} + +function IsAlias(typeA, typeB) { + if (typeA == typeB) + return true; + + if (AreBothIn(typeA, typeB, WEBGL_TYPES)) + return true; + + return false; +} + +function TestContextRetrieval(creationType, requestType, functionalTypeSet) { + var canvas = document.createElement('canvas'); + var createdGL = canvas.getContext(creationType); + + var didCreationSucceed = (createdGL != null); + if (creationType in functionalTypeSet) { + ok(createdGL, 'Context creation should succeed for type \'' + + creationType + '\''); + } else { + ok(!createdGL, 'Context creation should fail for type \'' + + creationType + '\''); + return; + } + + var requestedGL = canvas.getContext(requestType); + + if (requestType in functionalTypeSet && + IsAlias(creationType, requestType)) + { + ok(requestedGL, 'Request for \'' + requestType + '\' from \'' + + creationType + '\' should succeed.'); + ok(requestedGL == createdGL, 'Request for \'' + requestType + + '\' from \'' + creationType + + '\' should match.'); + } else { + ok(!requestedGL, 'Request for \'' + requestType + '\' from \'' + + creationType + '\' should fail.'); + } +} + +function IsWebGLFunctional() { + var canvas = document.createElement('canvas'); + return canvas.getContext('experimental-webgl') != null; +} +function IsWebGLConformant() { + var canvas = document.createElement('canvas'); + return canvas.getContext('webgl') != null; +} + +var typeList = ['2d', 'experimental-webgl', 'webgl']; +var functionalTypeSet = {}; +functionalTypeSet['2d'] = true; + +if (IsWebGLFunctional()) + functionalTypeSet['experimental-webgl'] = true; + +if (IsWebGLConformant()) + functionalTypeSet['webgl'] = true; + +for (var i in typeList) { + var creationType = typeList[i]; + + for (var j in typeList) { + var requestType = typeList[j]; + + TestContextRetrieval(creationType, requestType, functionalTypeSet); + } +} + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/test/webgl-mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/test/webgl-mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/test/webgl-mochitest.ini 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/test/webgl-mochitest.ini 2014-11-26 21:45:57.000000000 +0000 @@ -12,7 +12,8 @@ [webgl-mochitest/test_fb_param.html] [webgl-mochitest/test_fb_param_crash.html] [webgl-mochitest/test_hidden_alpha.html] -fail-if = (os == 'b2g') +skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so) +[webgl-mochitest/test_implicit_color_buffer_float.html] [webgl-mochitest/test_highp_fs.html] [webgl-mochitest/test_no_arr_points.html] skip-if = android_version == '10' #Android 2.3 aws only; bug 1030942 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL1Context.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL1Context.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL1Context.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL1Context.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -4,47 +4,48 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGL1Context.h" -#include "mozilla/dom/WebGLRenderingContextBinding.h" +#include "mozilla/dom/WebGLRenderingContextBinding.h" #include "mozilla/Telemetry.h" -using namespace mozilla; +namespace mozilla { -// ----------------------------------------------------------------------------- -// CONSTRUCTOR & DESTRUCTOR +/*static*/ WebGL1Context* +WebGL1Context::Create() +{ + return new WebGL1Context(); +} WebGL1Context::WebGL1Context() : WebGLContext() { - } WebGL1Context::~WebGL1Context() { - } - -// ----------------------------------------------------------------------------- -// IMPLEMENT nsWrapperCache +//////////////////////////////////////// +// nsWrapperCache JSObject* -WebGL1Context::WrapObject(JSContext *cx) +WebGL1Context::WrapObject(JSContext* cx) { return dom::WebGLRenderingContextBinding::Wrap(cx, this); } +} // namespace mozilla -// ----------------------------------------------------------------------------- -// INSTANCING nsIDOMWebGLRenderingContext +//////////////////////////////////////// +// nsIDOMWebGLRenderingContext nsresult -NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult) +NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** out_result) { - Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); - nsIDOMWebGLRenderingContext* ctx = new WebGL1Context(); + mozilla::Telemetry::Accumulate(mozilla::Telemetry::CANVAS_WEBGL_USED, 1); - NS_ADDREF(*aResult = ctx); + nsIDOMWebGLRenderingContext* ctx = mozilla::WebGL1Context::Create(); + + NS_ADDREF(*out_result = ctx); return NS_OK; } - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL1Context.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL1Context.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL1Context.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL1Context.h 2014-11-26 21:45:57.000000000 +0000 @@ -3,8 +3,8 @@ * 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/. */ -#ifndef WEBGL1CONTEXT_H_ -#define WEBGL1CONTEXT_H_ +#ifndef WEBGL_1_CONTEXT_H_ +#define WEBGL_1_CONTEXT_H_ #include "WebGLContext.h" @@ -13,34 +13,23 @@ class WebGL1Context : public WebGLContext { -// ----------------------------------------------------------------------------- -// PUBLIC public: + static WebGL1Context* Create(); - // ------------------------------------------------------------------------- - // CONSTRUCTOR & DESTRUCTOR - +private: WebGL1Context(); - virtual ~WebGL1Context(); - - // ------------------------------------------------------------------------- - // IMPLEMENT WebGLContext +public: + virtual ~WebGL1Context(); - virtual bool IsWebGL2() const MOZ_OVERRIDE - { + virtual bool IsWebGL2() const MOZ_OVERRIDE { return false; } - - // ------------------------------------------------------------------------- - // IMPLEMENT nsWrapperCache - - virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; - - + // nsWrapperCache + virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; }; } // namespace mozilla -#endif +#endif // WEBGL_1_CONTEXT_H_ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2Context.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2Context.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2Context.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2Context.h 2014-11-26 21:45:57.000000000 +0000 @@ -164,17 +164,19 @@ bool ValidateClearBuffer(const char* info, GLenum buffer, GLint drawbuffer, size_t elemCount); + // ------------------------------------------------------------------------- // Query Objects - WebGL2ContextQueries.cpp - // TODO(djg): Implemented in WebGLContext - /* already_AddRefed CreateQuery(); + + already_AddRefed CreateQuery(); void DeleteQuery(WebGLQuery* query); bool IsQuery(WebGLQuery* query); void BeginQuery(GLenum target, WebGLQuery* query); void EndQuery(GLenum target); - JS::Value GetQuery(JSContext*, GLenum target, GLenum pname); */ + already_AddRefed GetQuery(GLenum target, GLenum pname); void GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS::MutableHandleValue retval); + // ------------------------------------------------------------------------- // Sampler Objects - WebGL2ContextSamplers.cpp @@ -204,6 +206,7 @@ // ------------------------------------------------------------------------- // Transform Feedback - WebGL2ContextTransformFeedback.cpp + already_AddRefed CreateTransformFeedback(); void DeleteTransformFeedback(WebGLTransformFeedback* tf); bool IsTransformFeedback(WebGLTransformFeedback* tf); @@ -245,7 +248,6 @@ */ private: - WebGL2Context(); bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2ContextQueries.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2ContextQueries.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2ContextQueries.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2ContextQueries.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -5,24 +5,349 @@ #include "WebGL2Context.h" #include "GLContext.h" +#include "WebGLQuery.h" using namespace mozilla; using namespace mozilla::dom; +/* + * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with + * SAMPLES_PASSED on desktop. + * + * OpenGL ES 3.0 spec 4.1.6 + * If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an + * implementation may choose to use a less precise version of the test which + * can additionally set the samples-boolean state to TRUE in some other + * implementation-dependent cases. + */ + +static const char* +GetQueryTargetEnumString(GLenum target) +{ + switch (target) + { + case LOCAL_GL_ANY_SAMPLES_PASSED: + return "ANY_SAMPLES_PASSED"; + case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return "ANY_SAMPLES_PASSED_CONSERVATIVE"; + case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"; + default: + break; + } + + MOZ_ASSERT(false, "Unknown query `target`."); + return "UNKNOWN_QUERY_TARGET"; +} + +static inline GLenum +SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target) +{ + MOZ_ASSERT(target == LOCAL_GL_ANY_SAMPLES_PASSED || + target == LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE, + "unknown occlusion query target"); + + if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) { + return target; + } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) { + return LOCAL_GL_ANY_SAMPLES_PASSED; + } + + return LOCAL_GL_SAMPLES_PASSED; +} + +WebGLQueryRefPtr* +WebGLContext::GetQueryTargetSlot(GLenum target) +{ + switch (target) { + case LOCAL_GL_ANY_SAMPLES_PASSED: + case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return &mActiveOcclusionQuery; + + case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return &mActiveTransformFeedbackQuery; + } + + return nullptr; +} + + // ------------------------------------------------------------------------- // Query Objects -// TODO(djg): Implemented in WebGLContext -/* - already_AddRefed CreateQuery(); - void DeleteQuery(WebGLQuery* query); - bool IsQuery(WebGLQuery* query); - void BeginQuery(GLenum target, WebGLQuery* query); - void EndQuery(GLenum target); - JS::Value GetQuery(JSContext*, GLenum target, GLenum pname); -*/ +already_AddRefed +WebGL2Context::CreateQuery() +{ + if (IsContextLost()) + return nullptr; + + if (mActiveOcclusionQuery && !gl->IsGLES()) { + /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt + * + * Calling either GenQueriesARB or DeleteQueriesARB while any query of + * any target is active causes an INVALID_OPERATION error to be + * generated. + */ + GenerateWarning("createQuery: the WebGL 2 prototype might generate " + "INVALID_OPERATION when creating a query object while " + "one other is active."); + /* + * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a + * good mechanism to do this yet. See bug 898404. + */ + } + + nsRefPtr globj = new WebGLQuery(this); + + return globj.forget(); +} + +void +WebGL2Context::DeleteQuery(WebGLQuery* query) +{ + if (IsContextLost()) + return; + + if (!query) + return; + + if (query->IsDeleted()) + return; + + if (query->IsActive()) + EndQuery(query->mType); + + if (mActiveOcclusionQuery && !gl->IsGLES()) { + /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt + * + * Calling either GenQueriesARB or DeleteQueriesARB while any query of + * any target is active causes an INVALID_OPERATION error to be + * generated. + */ + GenerateWarning("deleteQuery: the WebGL 2 prototype might generate " + "INVALID_OPERATION when deleting a query object while " + "one other is active."); + } + + query->RequestDelete(); +} + +bool +WebGL2Context::IsQuery(WebGLQuery* query) +{ + if (IsContextLost()) + return false; + + if (!query) + return false; + + return (ValidateObjectAllowDeleted("isQuery", query) && + !query->IsDeleted() && + query->HasEverBeenActive()); +} + +void +WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query) +{ + if (IsContextLost()) + return; + + WebGLRefPtr* targetSlot = GetQueryTargetSlot(target); + if (!targetSlot) { + ErrorInvalidEnum("beginQuery: unknown query target"); + return; + } + + if (!query) { + /* SPECS BeginQuery.1 + * http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt + * BeginQueryEXT sets the active query object name for the query type given + * by to . If BeginQueryEXT is called with an of zero, if + * the active query object name for is non-zero (for the targets + * ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the + * active query for either target is non-zero), if is the name of an + * existing query object whose type does not match , or if is the + * active query object name for any query type, the error INVALID_OPERATION is + * generated. + */ + ErrorInvalidOperation("beginQuery: query should not be null"); + return; + } + + if (query->IsDeleted()) { + /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt + * BeginQueryEXT fails and an INVALID_OPERATION error is generated if + * is not a name returned from a previous call to GenQueriesEXT, or if such + * a name has since been deleted with DeleteQueriesEXT. + */ + ErrorInvalidOperation("beginQuery: query has been deleted"); + return; + } + + if (query->HasEverBeenActive() && + query->mType != target) + { + /* + * See SPECS BeginQuery.1 + */ + ErrorInvalidOperation("beginQuery: target doesn't match with the query type"); + return; + } + + if (*targetSlot) { + /* + * See SPECS BeginQuery.1 + */ + ErrorInvalidOperation("beginQuery: an other query already active"); + return; + } + + if (!query->HasEverBeenActive()) { + query->mType = target; + } + + MakeContextCurrent(); + + if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) { + gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->mGLName); + } else { + gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName); + } + + *targetSlot = query; +} + +void +WebGL2Context::EndQuery(GLenum target) +{ + if (IsContextLost()) + return; + + WebGLRefPtr* targetSlot = GetQueryTargetSlot(target); + if (!targetSlot) { + ErrorInvalidEnum("endQuery: unknown query target"); + return; + } + + if (!*targetSlot || target != (*targetSlot)->mType) { + /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt + * marks the end of the sequence of commands to be tracked for the query type + * given by . The active query object for is updated to + * indicate that query results are not available, and the active query object + * name for is reset to zero. When the commands issued prior to + * EndQueryEXT have completed and a final query result is available, the + * query object active when EndQueryEXT is called is updated by the GL. The + * query object is updated to indicate that the query results are available + * and to contain the query result. If the active query object name for + * is zero when EndQueryEXT is called, the error INVALID_OPERATION + * is generated. + */ + ErrorInvalidOperation("endQuery: There is no active query of type %s.", + GetQueryTargetEnumString(target)); + return; + } + + MakeContextCurrent(); + + if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) { + gl->fEndQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + } else { + gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target)); + } + + *targetSlot = nullptr; +} + +already_AddRefed +WebGL2Context::GetQuery(GLenum target, GLenum pname) +{ + if (IsContextLost()) + return nullptr; + + WebGLRefPtr* targetSlot = GetQueryTargetSlot(target); + if (!targetSlot) { + ErrorInvalidEnum("getQuery: unknown query target"); + return nullptr; + } + + if (pname != LOCAL_GL_CURRENT_QUERY) { + /* OpenGL ES 3.0 spec 6.1.7 + * pname must be CURRENT_QUERY. + */ + ErrorInvalidEnum("getQuery: pname must be CURRENT_QUERY"); + return nullptr; + } + + nsRefPtr tmp = targetSlot->get(); + return tmp.forget(); +} + void WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS::MutableHandleValue retval) { - MOZ_CRASH("Not Implemented"); + retval.set(JS::NullValue()); + + if (IsContextLost()) + return; + + if (!query) { + /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1) + * If id is not the name of a query object, or if the query object named by id is + * currently active, then an INVALID_OPERATION error is generated. pname must be + * QUERY_RESULT or QUERY_RESULT_AVAILABLE. + */ + ErrorInvalidOperation("getQueryObject: query should not be null"); + return; + } + + if (query->IsDeleted()) { + // See (spec getQueryObject 1) + ErrorInvalidOperation("getQueryObject: query has been deleted"); + return; + } + + if (query->IsActive()) { + // See (spec getQueryObject 1) + ErrorInvalidOperation("getQueryObject: query is active"); + return; + } + + if (!query->HasEverBeenActive()) { + /* See (spec getQueryObject 1) + * If this instance of WebGLQuery has never been active before, that mean that + * query->mGLName is not a query object yet. + */ + ErrorInvalidOperation("getQueryObject: query has never been active"); + return; + } + + MakeContextCurrent(); + GLuint returned = 0; + switch (pname) { + case LOCAL_GL_QUERY_RESULT_AVAILABLE: + gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned); + retval.set(JS::BooleanValue(returned != 0)); + return; + + case LOCAL_GL_QUERY_RESULT: + gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT, &returned); + + if (query->mType == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) { + retval.set(JS::NumberValue(returned)); + return; + } + + /* + * test (returned != 0) is important because ARB_occlusion_query on desktop drivers + * return the number of samples drawed when the OpenGL ES extension + * ARB_occlusion_query_boolean return only a boolean if a sample has been drawed. + */ + retval.set(JS::BooleanValue(returned != 0)); + return; + + default: + break; + } + + ErrorInvalidEnum("getQueryObject: pname must be QUERY_RESULT{_AVAILABLE}"); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2ContextSamplers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2ContextSamplers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2ContextSamplers.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2ContextSamplers.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGL2Context.h" +#include "WebGLSampler.h" #include "GLContext.h" using namespace mozilla; @@ -12,67 +13,206 @@ already_AddRefed WebGL2Context::CreateSampler() { - MOZ_CRASH("Not Implemented."); - return nullptr; + if (IsContextLost()) + return nullptr; + + GLuint sampler; + MakeContextCurrent(); + gl->fGenSamplers(1, &sampler); + + nsRefPtr globj = new WebGLSampler(this, sampler); + return globj.forget(); } void WebGL2Context::DeleteSampler(WebGLSampler* sampler) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!ValidateObjectAllowDeletedOrNull("deleteSampler", sampler)) + return; + + if (!sampler || sampler->IsDeleted()) + return; + + sampler->RequestDelete(); } bool WebGL2Context::IsSampler(WebGLSampler* sampler) { - MOZ_CRASH("Not Implemented."); - return false; + if (IsContextLost()) + return false; + + if (!sampler) + return false; + + if (!ValidateObjectAllowDeleted("isSampler", sampler)) + return false; + + if (sampler->IsDeleted()) + return false; + + return !sampler->HasEverBeenBound(); } void WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!ValidateObjectAllowDeletedOrNull("bindSampler", sampler)) + return; + + if (GLint(unit) >= mGLMaxTextureUnits) + return ErrorInvalidValue("bindSampler: unit must be < %d", mGLMaxTextureUnits); + + if (sampler && sampler->IsDeleted()) + return ErrorInvalidOperation("bindSampler: binding deleted sampler"); + + WebGLContextUnchecked::BindSampler(unit, sampler); } void WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameteri: invalid sampler"); + + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri")) + return; + + WebGLContextUnchecked::SamplerParameteri(sampler, pname, param); } void WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Int32Array& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameteriv: invalid sampler"); + + param.ComputeLengthAndData(); + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv")) + return; + + WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data()); } void WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Sequence& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameteriv: invalid sampler"); + + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv")) + return; + + WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements()); } void WebGL2Context::SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameterf: invalid sampler"); + + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf")) + return; + + WebGLContextUnchecked::SamplerParameterf(sampler, pname, param); } void WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Float32Array& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameterfv: invalid sampler"); + + param.ComputeLengthAndData(); + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv")) + return; + + WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data()); } void WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Sequence& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameterfv: invalid sampler"); + + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv")) + return; + + WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements()); } void WebGL2Context::GetSamplerParameter(JSContext*, WebGLSampler* sampler, GLenum pname, JS::MutableHandleValue retval) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("getSamplerParameter: invalid sampler"); + + if (!ValidateSamplerParameterName(pname, "getSamplerParameter")) + return; + + retval.set(JS::NullValue()); + + switch (pname) { + case LOCAL_GL_TEXTURE_MIN_FILTER: + case LOCAL_GL_TEXTURE_MAG_FILTER: + case LOCAL_GL_TEXTURE_WRAP_S: + case LOCAL_GL_TEXTURE_WRAP_T: + case LOCAL_GL_TEXTURE_WRAP_R: + case LOCAL_GL_TEXTURE_COMPARE_MODE: + case LOCAL_GL_TEXTURE_COMPARE_FUNC: + retval.set(JS::Int32Value( + WebGLContextUnchecked::GetSamplerParameteriv(sampler, pname))); + return; + + case LOCAL_GL_TEXTURE_MIN_LOD: + case LOCAL_GL_TEXTURE_MAX_LOD: + retval.set(JS::Float32Value( + WebGLContextUnchecked::GetSamplerParameterfv(sampler, pname))); + return; + } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2ContextTextures.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2ContextTextures.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGL2ContextTextures.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGL2ContextTextures.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -73,15 +73,12 @@ return true; } - if (IsCompressedTextureFormat(internalformat)) { + if (IsCompressedTextureFormat(internalformat)) return true; - } - const char* name = EnumName(internalformat); - if (name && name[0] != '[') - ErrorInvalidEnum("%s: invalid internal format %s", info, name); - else - ErrorInvalidEnum("%s: invalid internal format 0x%04X", info, internalformat); + nsCString name; + EnumName(internalformat, &name); + ErrorInvalidEnum("%s: invalid internal format %s", info, name.get()); return false; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLBindableName.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLBindableName.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLBindableName.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLBindableName.h 2014-11-26 21:45:57.000000000 +0000 @@ -14,20 +14,16 @@ namespace mozilla { -/** Represents a GL name that can be bound to a target. +/** Represents a binding to a GL binding point */ template -class WebGLBindableName +class WebGLBindable { public: + WebGLBindable() : mTarget(LOCAL_GL_NONE) { } + bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } - WebGLBindableName() - : mGLName(0) - , mTarget(LOCAL_GL_NONE) - { } - - void BindTo(T target) - { + void BindTo(T target) { MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE."); MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal."); @@ -37,22 +33,38 @@ OnTargetChanged(); } - bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } - GLuint GLName() const { return mGLName; } T Target() const { MOZ_ASSERT(HasEverBeenBound()); return mTarget; } protected: - //! Called after mTarget has been changed by BindTo(target). virtual void OnTargetChanged() {} - GLuint mGLName; T mTarget; }; + +/** Represents a GL name that can be bound to a target. + */ +template +class WebGLBindableName + : public WebGLBindable +{ +public: + + WebGLBindableName(GLuint name) + : WebGLBindable() + , mGLName(name) + { } + GLuint GLName() const { return mGLName; } + +protected: + const GLuint mGLName; +}; + + } // namespace mozilla #endif // !WEBGLBINDABLENAME_H_ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLBuffer.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLBuffer.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLBuffer.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLBuffer.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -12,13 +12,11 @@ using namespace mozilla; -WebGLBuffer::WebGLBuffer(WebGLContext *context) - : WebGLBindableName() +WebGLBuffer::WebGLBuffer(WebGLContext* context, GLuint buf) + : WebGLBindableName(buf) , WebGLContextBoundObject(context) , mByteLength(0) { - mContext->MakeContextCurrent(); - mContext->gl->fGenBuffers(1, &mGLName); mContext->mBuffers.insertBack(this); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLBuffer.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLBuffer.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLBuffer.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLBuffer.h 2014-11-26 21:45:57.000000000 +0000 @@ -27,7 +27,7 @@ , public WebGLContextBoundObject { public: - explicit WebGLBuffer(WebGLContext* aContext); + explicit WebGLBuffer(WebGLContext* context, GLuint buf); void Delete(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextAsyncQueries.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextAsyncQueries.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextAsyncQueries.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextAsyncQueries.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,351 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#include "WebGLContext.h" -#include "WebGLQuery.h" -#include "GLContext.h" - -using namespace mozilla; - -/* - * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with - * SAMPLES_PASSED on desktop. - * - * OpenGL ES 3.0 spec 4.1.6 - * If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an implementation - * may choose to use a less precise version of the test which can additionally set - * the samples-boolean state to TRUE in some other implementation-dependent cases. - */ - -static const char* -GetQueryTargetEnumString(GLenum target) -{ - switch (target) - { - case LOCAL_GL_ANY_SAMPLES_PASSED: - return "ANY_SAMPLES_PASSED"; - case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: - return "ANY_SAMPLES_PASSED_CONSERVATIVE"; - case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"; - default: - break; - } - - MOZ_ASSERT(false, "Unknown query `target`."); - return "UNKNOWN_QUERY_TARGET"; -} - -static inline GLenum -SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target) -{ - MOZ_ASSERT(target == LOCAL_GL_ANY_SAMPLES_PASSED || - target == LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE, - "unknown occlusion query target"); - - if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) { - return target; - } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) { - return LOCAL_GL_ANY_SAMPLES_PASSED; - } - - return LOCAL_GL_SAMPLES_PASSED; -} - -already_AddRefed -WebGLContext::CreateQuery() -{ - if (IsContextLost()) - return nullptr; - - if (mActiveOcclusionQuery && !gl->IsGLES()) { - /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt - * Calling either GenQueriesARB or DeleteQueriesARB while any query of - * any target is active causes an INVALID_OPERATION error to be - * generated. - */ - GenerateWarning("createQuery: the WebGL 2 prototype might generate INVALID_OPERATION" - "when creating a query object while one other is active."); - /* - * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a good - * mechanism to do this yet. See bug 898404. - */ - } - - nsRefPtr globj = new WebGLQuery(this); - - return globj.forget(); -} - -void -WebGLContext::DeleteQuery(WebGLQuery *query) -{ - if (IsContextLost()) - return; - - if (!query) - return; - - if (query->IsDeleted()) - return; - - if (query->IsActive()) { - EndQuery(query->mType); - } - - if (mActiveOcclusionQuery && !gl->IsGLES()) { - /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt - * Calling either GenQueriesARB or DeleteQueriesARB while any query of - * any target is active causes an INVALID_OPERATION error to be - * generated. - */ - GenerateWarning("deleteQuery: the WebGL 2 prototype might generate INVALID_OPERATION" - "when deleting a query object while one other is active."); - } - - query->RequestDelete(); -} - -void -WebGLContext::BeginQuery(GLenum target, WebGLQuery *query) -{ - if (IsContextLost()) - return; - - WebGLRefPtr* targetSlot = GetQueryTargetSlot(target, "beginQuery"); - if (!targetSlot) { - return; - } - - if (!query) { - /* SPECS BeginQuery.1 - * http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt - * BeginQueryEXT sets the active query object name for the query type given - * by to . If BeginQueryEXT is called with an of zero, if - * the active query object name for is non-zero (for the targets - * ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the - * active query for either target is non-zero), if is the name of an - * existing query object whose type does not match , or if is the - * active query object name for any query type, the error INVALID_OPERATION is - * generated. - */ - ErrorInvalidOperation("beginQuery: query should not be null"); - return; - } - - if (query->IsDeleted()) { - /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt - * BeginQueryEXT fails and an INVALID_OPERATION error is generated if - * is not a name returned from a previous call to GenQueriesEXT, or if such - * a name has since been deleted with DeleteQueriesEXT. - */ - ErrorInvalidOperation("beginQuery: query has been deleted"); - return; - } - - if (query->HasEverBeenActive() && - query->mType != target) - { - /* - * See SPECS BeginQuery.1 - */ - ErrorInvalidOperation("beginQuery: target doesn't match with the query type"); - return; - } - - if (*targetSlot) { - /* - * See SPECS BeginQuery.1 - */ - ErrorInvalidOperation("beginQuery: an other query already active"); - return; - } - - if (!query->HasEverBeenActive()) { - query->mType = target; - } - - MakeContextCurrent(); - - if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) { - gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->mGLName); - } else { - gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName); - } - - *targetSlot = query; -} - -void -WebGLContext::EndQuery(GLenum target) -{ - if (IsContextLost()) - return; - - WebGLRefPtr* targetSlot = GetQueryTargetSlot(target, "endQuery"); - if (!targetSlot) { - return; - } - - if (!*targetSlot || - target != (*targetSlot)->mType) - { - /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt - * marks the end of the sequence of commands to be tracked for the query type - * given by . The active query object for is updated to - * indicate that query results are not available, and the active query object - * name for is reset to zero. When the commands issued prior to - * EndQueryEXT have completed and a final query result is available, the - * query object active when EndQueryEXT is called is updated by the GL. The - * query object is updated to indicate that the query results are available - * and to contain the query result. If the active query object name for - * is zero when EndQueryEXT is called, the error INVALID_OPERATION - * is generated. - */ - ErrorInvalidOperation("endQuery: There is no active query of type %s.", - GetQueryTargetEnumString(target)); - return; - } - - MakeContextCurrent(); - - if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) { - gl->fEndQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); - } else { - gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target)); - } - - *targetSlot = nullptr; -} - -bool -WebGLContext::IsQuery(WebGLQuery *query) -{ - if (IsContextLost()) - return false; - - if (!query) - return false; - - return ValidateObjectAllowDeleted("isQuery", query) && - !query->IsDeleted() && - query->HasEverBeenActive(); -} - -already_AddRefed -WebGLContext::GetQuery(GLenum target, GLenum pname) -{ - if (IsContextLost()) - return nullptr; - - WebGLRefPtr* targetSlot = GetQueryTargetSlot(target, "getQuery"); - if (!targetSlot) { - return nullptr; - } - - if (pname != LOCAL_GL_CURRENT_QUERY) { - /* OpenGL ES 3.0 spec 6.1.7 - * pname must be CURRENT_QUERY. - */ - ErrorInvalidEnum("getQuery: pname must be CURRENT_QUERY"); - return nullptr; - } - - nsRefPtr tmp = targetSlot->get(); - return tmp.forget(); -} - -JS::Value -WebGLContext::GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname) -{ - if (IsContextLost()) - return JS::NullValue(); - - if (!query) { - /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1) - * If id is not the name of a query object, or if the query object named by id is - * currently active, then an INVALID_OPERATION error is generated. pname must be - * QUERY_RESULT or QUERY_RESULT_AVAILABLE. - */ - ErrorInvalidOperation("getQueryObject: query should not be null"); - return JS::NullValue(); - } - - if (query->IsDeleted()) { - // See (spec getQueryObject 1) - ErrorInvalidOperation("getQueryObject: query has been deleted"); - return JS::NullValue(); - } - - if (query->IsActive()) { - // See (spec getQueryObject 1) - ErrorInvalidOperation("getQueryObject: query is active"); - return JS::NullValue(); - } - - if (!query->HasEverBeenActive()) { - /* See (spec getQueryObject 1) - * If this instance of WebGLQuery has never been active before, that mean that - * query->mGLName is not a query object yet. - */ - ErrorInvalidOperation("getQueryObject: query has never been active"); - return JS::NullValue(); - } - - switch (pname) - { - case LOCAL_GL_QUERY_RESULT_AVAILABLE: - { - GLuint returned = 0; - - MakeContextCurrent(); - gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned); - - return JS::BooleanValue(returned != 0); - } - - case LOCAL_GL_QUERY_RESULT: - { - GLuint returned = 0; - - MakeContextCurrent(); - gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT, &returned); - - if (query->mType == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) { - return JS::NumberValue(uint32_t(returned)); - } - - /* - * test (returned != 0) is important because ARB_occlusion_query on desktop drivers - * return the number of samples drawed when the OpenGL ES extension - * ARB_occlusion_query_boolean return only a boolean if a sample has been drawed. - */ - return JS::BooleanValue(returned != 0); - } - - default: - break; - } - - ErrorInvalidEnum("getQueryObject: pname must be QUERY_RESULT{_AVAILABLE}"); - return JS::NullValue(); -} - -WebGLRefPtr* -WebGLContext::GetQueryTargetSlot(GLenum target, const char* infos) -{ - switch (target) { - case LOCAL_GL_ANY_SAMPLES_PASSED: - case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: - return &mActiveOcclusionQuery; - case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - return &mActiveTransformFeedbackQuery; - } - - ErrorInvalidEnum("%s: unknown query target", infos); - return nullptr; -} - - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextBuffers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextBuffers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextBuffers.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextBuffers.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -361,7 +361,11 @@ if (IsContextLost()) return nullptr; - nsRefPtr globj = new WebGLBuffer(this); + GLuint buf = 0; + MakeContextCurrent(); + gl->fGenBuffers(1, &buf); + + nsRefPtr globj = new WebGLBuffer(this, buf); return globj.forget(); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContext.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContext.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContext.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContext.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -7,15 +7,16 @@ #include "WebGLContextLossHandler.h" #include "WebGL1Context.h" -#include "WebGLObjectModel.h" -#include "WebGLExtensions.h" -#include "WebGLContextUtils.h" #include "WebGLBuffer.h" -#include "WebGLVertexAttribData.h" -#include "WebGLMemoryTracker.h" +#include "WebGLContextUtils.h" +#include "WebGLExtensions.h" #include "WebGLFramebuffer.h" -#include "WebGLVertexArray.h" +#include "WebGLMemoryTracker.h" +#include "WebGLObjectModel.h" #include "WebGLQuery.h" +#include "WebGLSampler.h" +#include "WebGLVertexArray.h" +#include "WebGLVertexAttribData.h" #include "GLBlitHelper.h" #include "AccessCheck.h" @@ -226,7 +227,7 @@ } WebGLContext::WebGLContext() - : gl(nullptr) + : WebGLContextUnchecked(nullptr) , mNeedsFakeNoAlpha(false) { mGeneration = 0; @@ -371,6 +372,8 @@ mPrograms.getLast()->DeleteOnce(); while (!mQueries.isEmpty()) mQueries.getLast()->DeleteOnce(); + while (!mSamplers.isEmpty()) + mSamplers.getLast()->DeleteOnce(); mBlackOpaqueTexture2D = nullptr; mBlackOpaqueTextureCubeMap = nullptr; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextExtensions.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextExtensions.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextExtensions.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextExtensions.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -186,6 +186,19 @@ return name.Equals(other, nsCaseInsensitiveCStringComparator()); } +WebGLExtensionBase* +WebGLContext::EnableSupportedExtension(JSContext* js, WebGLExtensionID ext) +{ + if (!IsExtensionEnabled(ext)) { + if (!IsExtensionSupported(js, ext)) + return nullptr; + + EnableExtension(ext); + } + + return mExtensions[ext]; +} + void WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, JS::MutableHandle aRetval, @@ -201,8 +214,7 @@ WebGLExtensionID ext = WebGLExtensionID::Unknown; // step 1: figure what extension is wanted - for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) - { + for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) { WebGLExtensionID extension = WebGLExtensionID(i); if (CompareWebGLExtensionName(name, GetExtensionString(extension))) { @@ -211,8 +223,7 @@ } } - if (ext == WebGLExtensionID::Unknown) - { + if (ext == WebGLExtensionID::Unknown) { /** * We keep backward compatibility for these deprecated vendor-prefixed * alias. Do not add new ones anymore. Hide it behind the @@ -254,11 +265,27 @@ } // step 3: if the extension hadn't been previously been created, create it now, thus enabling it - if (!IsExtensionEnabled(ext)) { - EnableExtension(ext); + WebGLExtensionBase* extObj = EnableSupportedExtension(cx, ext); + if (!extObj) { + aRetval.set(nullptr); + return; + } + + // Step 4: Enable any implied extensions. + switch (ext) { + case WebGLExtensionID::OES_texture_float: + EnableSupportedExtension(cx, WebGLExtensionID::WEBGL_color_buffer_float); + break; + + case WebGLExtensionID::OES_texture_half_float: + EnableSupportedExtension(cx, WebGLExtensionID::EXT_color_buffer_half_float); + break; + + default: + break; } - aRetval.set(WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv)); + aRetval.set(WebGLObjectAsJSObject(cx, extObj, rv)); } void diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextGL.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextGL.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextGL.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextGL.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -1372,7 +1372,12 @@ { if (IsContextLost()) return nullptr; - nsRefPtr globj = new WebGLTexture(this); + + GLuint tex = 0; + MakeContextCurrent(); + gl->fGenTextures(1, &tex); + + nsRefPtr globj = new WebGLTexture(this, tex); return globj.forget(); } @@ -1439,24 +1444,31 @@ MakeContextCurrent(); + GLint i = 0; + + if (IsWebGL2()) { + switch (pname) { + case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS: + case LOCAL_GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + gl->fGetProgramiv(progname, pname, &i); + return JS::Int32Value(i); + } + } + switch (pname) { case LOCAL_GL_ATTACHED_SHADERS: case LOCAL_GL_ACTIVE_UNIFORMS: case LOCAL_GL_ACTIVE_ATTRIBUTES: - { - GLint i = 0; gl->fGetProgramiv(progname, pname, &i); return JS::Int32Value(i); - } + case LOCAL_GL_DELETE_STATUS: return JS::BooleanValue(prog->IsDeleteRequested()); + case LOCAL_GL_LINK_STATUS: - { return JS::BooleanValue(prog->LinkStatus()); - } + case LOCAL_GL_VALIDATE_STATUS: - { - GLint i = 0; #ifdef XP_MACOSX // See comment in ValidateProgram below. if (gl->WorkAroundDriverBugs()) @@ -1467,8 +1479,6 @@ gl->fGetProgramiv(progname, pname, &i); #endif return JS::BooleanValue(bool(i)); - } - break; default: ErrorInvalidEnumInfo("getProgramParameter: parameter", pname); @@ -3098,7 +3108,12 @@ { if (IsContextLost()) return nullptr; - nsRefPtr globj = new WebGLFramebuffer(this); + + GLuint fbo = 0; + MakeContextCurrent(); + gl->fGenFramebuffers(1, &fbo); + + nsRefPtr globj = new WebGLFramebuffer(this, fbo); return globj.forget(); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContext.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContext.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContext.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContext.h 2014-11-26 21:45:57.000000000 +0000 @@ -15,6 +15,7 @@ #include "GLDefs.h" #include "WebGLActiveInfo.h" +#include "WebGLContextUnchecked.h" #include "WebGLObjectModel.h" #include "WebGLRenderbuffer.h" #include "WebGLTexture.h" @@ -71,16 +72,17 @@ class WebGLActiveInfo; class WebGLExtensionBase; class WebGLBuffer; -struct WebGLVertexAttribData; class WebGLShader; class WebGLProgram; class WebGLQuery; class WebGLUniformLocation; class WebGLFramebuffer; class WebGLRenderbuffer; +class WebGLSampler; class WebGLShaderPrecisionFormat; class WebGLTexture; class WebGLVertexArray; +struct WebGLVertexAttribData; namespace dom { class ImageData; @@ -94,6 +96,8 @@ class SourceSurface; } +typedef WebGLRefPtr WebGLQueryRefPtr; + WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format); void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow); @@ -127,10 +131,29 @@ // From WebGLContextUtils TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget); +class WebGLIntOrFloat { + enum { + Int, + Float + } mType; + union { + GLint i; + GLfloat f; + } mValue; + +public: + explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; } + explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; } + + GLint AsInt() const { return (mType == Int) ? mValue.i : NS_lroundf(mValue.f); } + GLfloat AsFloat() const { return (mType == Float) ? mValue.f : GLfloat(mValue.i); } +}; + class WebGLContext : public nsIDOMWebGLRenderingContext, public nsICanvasRenderingContextInternal, public nsSupportsWeakReference, + public WebGLContextUnchecked, public WebGLRectangleObject, public nsWrapperCache, public SupportsWeakPtr @@ -220,7 +243,11 @@ * This version is like gl::GLenumToStr but with out the GL_ prefix to * keep consistency with how errors are reported from WebGL. */ - static const char *EnumName(GLenum glenum); + + // Returns nullptr if glenum is unknown. + static const char* EnumName(GLenum glenum); + // Returns hex formatted version of glenum if glenum is unknown. + static void EnumName(GLenum glenum, nsACString* out_name); bool IsCompressedTextureFormat(GLenum format); bool IsTextureFormatCompressed(TexInternalFormat format); @@ -324,7 +351,7 @@ void ClearDepth(GLclampf v); void ClearStencil(GLint v); void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a); - void CompileShader(WebGLShader *shader); + void CompileShader(WebGLShader* shader); void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, @@ -797,30 +824,6 @@ void RestoreContext(); // ----------------------------------------------------------------------------- -// Asynchronous Queries (WebGLContextAsyncQueries.cpp) -public: - already_AddRefed CreateQuery(); - void DeleteQuery(WebGLQuery *query); - void BeginQuery(GLenum target, WebGLQuery *query); - void EndQuery(GLenum target); - bool IsQuery(WebGLQuery *query); - already_AddRefed GetQuery(GLenum target, GLenum pname); - JS::Value GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname); - void GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname, - JS::MutableHandle retval) { - retval.set(GetQueryObject(cx, query, pname)); - } - -private: - // ANY_SAMPLES_PASSED(_CONSERVATIVE) slot - WebGLRefPtr mActiveOcclusionQuery; - - // LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN slot - WebGLRefPtr mActiveTransformFeedbackQuery; - - WebGLRefPtr* GetQueryTargetSlot(GLenum target, const char* infos); - -// ----------------------------------------------------------------------------- // Buffer Objects (WebGLContextBuffers.cpp) public: void BindBuffer(GLenum target, WebGLBuffer* buf); @@ -854,6 +857,14 @@ bool ValidateBufferUsageEnum(GLenum target, const char* infos); // ----------------------------------------------------------------------------- +// Queries (WebGL2ContextQueries.cpp) +protected: + WebGLQueryRefPtr* GetQueryTargetSlot(GLenum target); + + WebGLQueryRefPtr mActiveOcclusionQuery; + WebGLQueryRefPtr mActiveTransformFeedbackQuery; + +// ----------------------------------------------------------------------------- // State and State Requests (WebGLContextState.cpp) public: void Disable(GLenum cap); @@ -1005,8 +1016,6 @@ return ((x + y - 1) / y) * y; } - nsRefPtr gl; - CheckedUint32 mGeneration; WebGLContextOptions mOptions; @@ -1060,6 +1069,9 @@ return mGLMaxVertexAttribs; } + + bool IsFormatValidForFB(GLenum sizedFormat) const; + protected: // Represents current status of the context with respect to context loss. // That is, whether the context is lost, and what part of the context loss @@ -1092,6 +1104,10 @@ // enable an extension. the extension should not be enabled before. void EnableExtension(WebGLExtensionID ext); + // Enable an extension if it's supported. Return the extension on success. + WebGLExtensionBase* EnableSupportedExtension(JSContext* js, + WebGLExtensionID ext); + // returns true if the extension has been enabled by calling getExtension. bool IsExtensionEnabled(WebGLExtensionID ext) const; @@ -1138,6 +1154,10 @@ bool ValidateCopyTexImage(GLenum internalformat, WebGLTexImageFunc func, WebGLTexDimensions dims); + + bool ValidateSamplerParameterName(GLenum pname, const char* info); + bool ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info); + bool ValidateTexImage(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint zoffset, @@ -1325,6 +1345,9 @@ LinkedList mFramebuffers; LinkedList mVertexArrays; + // TODO(djg): Does this need a rethink? Should it be WebGL2Context? + LinkedList mSamplers; + WebGLRefPtr mDefaultVertexArray; // PixelStore parameters @@ -1440,6 +1463,7 @@ friend class WebGLProgram; friend class WebGLQuery; friend class WebGLBuffer; + friend class WebGLSampler; friend class WebGLShader; friend class WebGLUniformLocation; friend class WebGLVertexArray; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextUnchecked.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextUnchecked.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextUnchecked.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextUnchecked.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* 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/. */ + +#include "WebGLContextUnchecked.h" + +#include "GLContext.h" +#include "WebGLSampler.h" + +namespace mozilla { + +WebGLContextUnchecked::WebGLContextUnchecked(gl::GLContext* gl) + : gl(gl) +{ } + + +// ----------------------------------------------------------------------------- +// Sampler Objects + +void +WebGLContextUnchecked::BindSampler(GLuint unit, WebGLSampler* sampler) +{ + gl->MakeCurrent(); + gl->fBindSampler(unit, sampler ? sampler->GLName() : 0); + if (sampler) + sampler->BindTo(LOCAL_GL_SAMPLER_BINDING); +} + +GLint +WebGLContextUnchecked::GetSamplerParameteriv(WebGLSampler* sampler, + GLenum pname) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + + GLint param = 0; + gl->MakeCurrent(); + gl->fGetSamplerParameteriv(sampler->GLName(), pname, ¶m); + + return param; +} + +GLfloat +WebGLContextUnchecked::GetSamplerParameterfv(WebGLSampler* sampler, + GLenum pname) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + + GLfloat param = 0.0f; + gl->MakeCurrent(); + gl->fGetSamplerParameterfv(sampler->GLName(), pname, ¶m); + return param; +} + +void +WebGLContextUnchecked::SamplerParameteri(WebGLSampler* sampler, + GLenum pname, + GLint param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameteri(sampler->GLName(), pname, param); +} + +void +WebGLContextUnchecked::SamplerParameteriv(WebGLSampler* sampler, + GLenum pname, + const GLint* param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameteriv(sampler->GLName(), pname, param); +} + +void +WebGLContextUnchecked::SamplerParameterf(WebGLSampler* sampler, + GLenum pname, + GLfloat param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameterf(sampler->GLName(), pname, param); +} + +void +WebGLContextUnchecked::SamplerParameterfv(WebGLSampler* sampler, + GLenum pname, + const GLfloat* param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameterfv(sampler->GLName(), pname, param); +} + +} // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextUnchecked.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextUnchecked.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextUnchecked.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextUnchecked.h 2014-11-26 21:45:57.000000000 +0000 @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* 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/. */ + +#ifndef WEBGLCONTEXTUNCHECKED_H +#define WEBGLCONTEXTUNCHECKED_H + +#include "GLDefs.h" +#include "WebGLTypes.h" +#include "nsAutoPtr.h" +#include "nsTArray.h" + +namespace mozilla { + +class WebGLSampler; +namespace gl { + class GLContext; +} + +class WebGLContextUnchecked +{ +public: + explicit WebGLContextUnchecked(gl::GLContext* gl); + + // ------------------------------------------------------------------------- + // Sampler Objects + void BindSampler(GLuint unit, WebGLSampler* sampler); + + GLint GetSamplerParameteriv(WebGLSampler* sampler, GLenum pname); + GLfloat GetSamplerParameterfv(WebGLSampler* sampler, GLenum pname); + + void SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param); + void SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const GLint* param); + void SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param); + void SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const GLfloat* param); + +protected: // data + nsRefPtr gl; +}; + +} // namespace mozilla + +#endif // !WEBGLCONTEXTUNCHECKED_H diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextUtils.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextUtils.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextUtils.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextUtils.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -14,6 +14,7 @@ #include "nsIDOMEvent.h" #include "nsIScriptSecurityManager.h" #include "nsIVariant.h" +#include "nsPrintfCString.h" #include "nsServiceManagerUtils.h" #include "prprf.h" #include "WebGLBuffer.h" @@ -505,7 +506,10 @@ void WebGLContext::ErrorInvalidEnumInfo(const char *info, GLenum enumvalue) { - return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue); + nsCString name; + EnumName(enumvalue, &name); + + return ErrorInvalidEnum("%s: invalid enum value %s", info, name.get()); } void @@ -574,6 +578,7 @@ } } +// This version is 'fallible' and will return NULL if glenum is not recognized. const char* WebGLContext::EnumName(GLenum glenum) { @@ -625,10 +630,289 @@ XX(UNSIGNED_SHORT_4_4_4_4); XX(UNSIGNED_SHORT_5_5_5_1); XX(UNSIGNED_SHORT_5_6_5); + XX(READ_BUFFER); + XX(UNPACK_ROW_LENGTH); + XX(UNPACK_SKIP_ROWS); + XX(UNPACK_SKIP_PIXELS); + XX(PACK_ROW_LENGTH); + XX(PACK_SKIP_ROWS); + XX(PACK_SKIP_PIXELS); + XX(COLOR); + XX(DEPTH); + XX(STENCIL); + XX(RED); + XX(RGB8); + XX(RGBA8); + XX(RGB10_A2); + XX(TEXTURE_BINDING_3D); + XX(UNPACK_SKIP_IMAGES); + XX(UNPACK_IMAGE_HEIGHT); + XX(TEXTURE_WRAP_R); + XX(MAX_3D_TEXTURE_SIZE); + XX(UNSIGNED_INT_2_10_10_10_REV); + XX(MAX_ELEMENTS_VERTICES); + XX(MAX_ELEMENTS_INDICES); + XX(TEXTURE_MIN_LOD); + XX(TEXTURE_MAX_LOD); + XX(TEXTURE_BASE_LEVEL); + XX(TEXTURE_MAX_LEVEL); + XX(MIN); + XX(MAX); + XX(DEPTH_COMPONENT24); + XX(MAX_TEXTURE_LOD_BIAS); + XX(TEXTURE_COMPARE_MODE); + XX(TEXTURE_COMPARE_FUNC); + XX(CURRENT_QUERY); + XX(QUERY_RESULT); + XX(QUERY_RESULT_AVAILABLE); + XX(STREAM_READ); + XX(STREAM_COPY); + XX(STATIC_READ); + XX(STATIC_COPY); + XX(DYNAMIC_READ); + XX(DYNAMIC_COPY); + XX(MAX_DRAW_BUFFERS); + XX(DRAW_BUFFER0); + XX(DRAW_BUFFER1); + XX(DRAW_BUFFER2); + XX(DRAW_BUFFER3); + XX(DRAW_BUFFER4); + XX(DRAW_BUFFER5); + XX(DRAW_BUFFER6); + XX(DRAW_BUFFER7); + XX(DRAW_BUFFER8); + XX(DRAW_BUFFER9); + XX(DRAW_BUFFER10); + XX(DRAW_BUFFER11); + XX(DRAW_BUFFER12); + XX(DRAW_BUFFER13); + XX(DRAW_BUFFER14); + XX(DRAW_BUFFER15); + XX(MAX_FRAGMENT_UNIFORM_COMPONENTS); + XX(MAX_VERTEX_UNIFORM_COMPONENTS); + XX(SAMPLER_3D); + XX(SAMPLER_2D_SHADOW); + XX(FRAGMENT_SHADER_DERIVATIVE_HINT); + XX(PIXEL_PACK_BUFFER); + XX(PIXEL_UNPACK_BUFFER); + XX(PIXEL_PACK_BUFFER_BINDING); + XX(PIXEL_UNPACK_BUFFER_BINDING); + XX(FLOAT_MAT2x3); + XX(FLOAT_MAT2x4); + XX(FLOAT_MAT3x2); + XX(FLOAT_MAT3x4); + XX(FLOAT_MAT4x2); + XX(FLOAT_MAT4x3); + XX(SRGB8); + XX(SRGB8_ALPHA8); + XX(COMPARE_REF_TO_TEXTURE); + XX(VERTEX_ATTRIB_ARRAY_INTEGER); + XX(MAX_ARRAY_TEXTURE_LAYERS); + XX(MIN_PROGRAM_TEXEL_OFFSET); + XX(MAX_PROGRAM_TEXEL_OFFSET); + XX(MAX_VARYING_COMPONENTS); + XX(TEXTURE_2D_ARRAY); + XX(TEXTURE_BINDING_2D_ARRAY); + XX(R11F_G11F_B10F); + XX(UNSIGNED_INT_10F_11F_11F_REV); + XX(RGB9_E5); + XX(UNSIGNED_INT_5_9_9_9_REV); + XX(TRANSFORM_FEEDBACK_BUFFER_MODE); + XX(MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS); + XX(TRANSFORM_FEEDBACK_VARYINGS); + XX(TRANSFORM_FEEDBACK_BUFFER_START); + XX(TRANSFORM_FEEDBACK_BUFFER_SIZE); + XX(TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + XX(RASTERIZER_DISCARD); + XX(MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); + XX(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS); + XX(INTERLEAVED_ATTRIBS); + XX(SEPARATE_ATTRIBS); + XX(TRANSFORM_FEEDBACK_BUFFER); + XX(TRANSFORM_FEEDBACK_BUFFER_BINDING); + XX(RGBA32UI); + XX(RGB32UI); + XX(RGBA16UI); + XX(RGB16UI); + XX(RGBA8UI); + XX(RGB8UI); + XX(RGBA32I); + XX(RGB32I); + XX(RGBA16I); + XX(RGB16I); + XX(RGBA8I); + XX(RGB8I); + XX(RED_INTEGER); + XX(RGB_INTEGER); + XX(RGBA_INTEGER); + XX(SAMPLER_2D_ARRAY); + XX(SAMPLER_2D_ARRAY_SHADOW); + XX(SAMPLER_CUBE_SHADOW); + XX(UNSIGNED_INT_VEC2); + XX(UNSIGNED_INT_VEC3); + XX(UNSIGNED_INT_VEC4); + XX(INT_SAMPLER_2D); + XX(INT_SAMPLER_3D); + XX(INT_SAMPLER_CUBE); + XX(INT_SAMPLER_2D_ARRAY); + XX(UNSIGNED_INT_SAMPLER_2D); + XX(UNSIGNED_INT_SAMPLER_3D); + XX(UNSIGNED_INT_SAMPLER_CUBE); + XX(UNSIGNED_INT_SAMPLER_2D_ARRAY); + XX(DEPTH_COMPONENT32F); + XX(DEPTH32F_STENCIL8); + XX(FLOAT_32_UNSIGNED_INT_24_8_REV); + XX(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + XX(FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE); + XX(FRAMEBUFFER_ATTACHMENT_RED_SIZE); + XX(FRAMEBUFFER_ATTACHMENT_GREEN_SIZE); + XX(FRAMEBUFFER_ATTACHMENT_BLUE_SIZE); + XX(FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE); + XX(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE); + XX(FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE); + XX(FRAMEBUFFER_DEFAULT); + XX(DEPTH_STENCIL_ATTACHMENT); + XX(UNSIGNED_NORMALIZED); + XX(DRAW_FRAMEBUFFER_BINDING); + XX(READ_FRAMEBUFFER); + XX(DRAW_FRAMEBUFFER); + XX(READ_FRAMEBUFFER_BINDING); + XX(RENDERBUFFER_SAMPLES); + XX(FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER); + XX(MAX_COLOR_ATTACHMENTS); + XX(COLOR_ATTACHMENT1); + XX(COLOR_ATTACHMENT2); + XX(COLOR_ATTACHMENT3); + XX(COLOR_ATTACHMENT4); + XX(COLOR_ATTACHMENT5); + XX(COLOR_ATTACHMENT6); + XX(COLOR_ATTACHMENT7); + XX(COLOR_ATTACHMENT8); + XX(COLOR_ATTACHMENT9); + XX(COLOR_ATTACHMENT10); + XX(COLOR_ATTACHMENT11); + XX(COLOR_ATTACHMENT12); + XX(COLOR_ATTACHMENT13); + XX(COLOR_ATTACHMENT14); + XX(COLOR_ATTACHMENT15); + XX(FRAMEBUFFER_INCOMPLETE_MULTISAMPLE); + XX(MAX_SAMPLES); + XX(RG); + XX(RG_INTEGER); + XX(R8); + XX(RG8); + XX(R16F); + XX(R32F); + XX(RG16F); + XX(RG32F); + XX(R8I); + XX(R8UI); + XX(R16I); + XX(R16UI); + XX(R32I); + XX(R32UI); + XX(RG8I); + XX(RG8UI); + XX(RG16I); + XX(RG16UI); + XX(RG32I); + XX(RG32UI); + XX(VERTEX_ARRAY_BINDING); + XX(R8_SNORM); + XX(RG8_SNORM); + XX(RGB8_SNORM); + XX(RGBA8_SNORM); + XX(SIGNED_NORMALIZED); + XX(PRIMITIVE_RESTART_FIXED_INDEX); + XX(COPY_READ_BUFFER); + XX(COPY_WRITE_BUFFER); + XX(UNIFORM_BUFFER); + XX(UNIFORM_BUFFER_BINDING); + XX(UNIFORM_BUFFER_START); + XX(UNIFORM_BUFFER_SIZE); + XX(MAX_VERTEX_UNIFORM_BLOCKS); + XX(MAX_FRAGMENT_UNIFORM_BLOCKS); + XX(MAX_COMBINED_UNIFORM_BLOCKS); + XX(MAX_UNIFORM_BUFFER_BINDINGS); + XX(MAX_UNIFORM_BLOCK_SIZE); + XX(MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS); + XX(MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS); + XX(UNIFORM_BUFFER_OFFSET_ALIGNMENT); + XX(ACTIVE_UNIFORM_BLOCKS); + XX(UNIFORM_TYPE); + XX(UNIFORM_SIZE); + XX(UNIFORM_BLOCK_INDEX); + XX(UNIFORM_OFFSET); + XX(UNIFORM_ARRAY_STRIDE); + XX(UNIFORM_MATRIX_STRIDE); + XX(UNIFORM_IS_ROW_MAJOR); + XX(UNIFORM_BLOCK_BINDING); + XX(UNIFORM_BLOCK_DATA_SIZE); + XX(UNIFORM_BLOCK_ACTIVE_UNIFORMS); + XX(UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES); + XX(UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER); + XX(UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER); + XX(MAX_VERTEX_OUTPUT_COMPONENTS); + XX(MAX_FRAGMENT_INPUT_COMPONENTS); + XX(MAX_SERVER_WAIT_TIMEOUT); + XX(OBJECT_TYPE); + XX(SYNC_CONDITION); + XX(SYNC_STATUS); + XX(SYNC_FLAGS); + XX(SYNC_FENCE); + XX(SYNC_GPU_COMMANDS_COMPLETE); + XX(UNSIGNALED); + XX(SIGNALED); + XX(ALREADY_SIGNALED); + XX(TIMEOUT_EXPIRED); + XX(CONDITION_SATISFIED); + XX(WAIT_FAILED); + XX(VERTEX_ATTRIB_ARRAY_DIVISOR); + XX(ANY_SAMPLES_PASSED); + XX(ANY_SAMPLES_PASSED_CONSERVATIVE); + XX(SAMPLER_BINDING); + XX(RGB10_A2UI); + XX(TEXTURE_SWIZZLE_R); + XX(TEXTURE_SWIZZLE_G); + XX(TEXTURE_SWIZZLE_B); + XX(TEXTURE_SWIZZLE_A); + XX(GREEN); + XX(BLUE); + XX(INT_2_10_10_10_REV); + XX(TRANSFORM_FEEDBACK); + XX(TRANSFORM_FEEDBACK_PAUSED); + XX(TRANSFORM_FEEDBACK_ACTIVE); + XX(TRANSFORM_FEEDBACK_BINDING); + XX(COMPRESSED_R11_EAC); + XX(COMPRESSED_SIGNED_R11_EAC); + XX(COMPRESSED_RG11_EAC); + XX(COMPRESSED_SIGNED_RG11_EAC); + XX(COMPRESSED_RGB8_ETC2); + XX(COMPRESSED_SRGB8_ETC2); + XX(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2); + XX(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2); + XX(COMPRESSED_RGBA8_ETC2_EAC); + XX(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC); + XX(TEXTURE_IMMUTABLE_FORMAT); + XX(MAX_ELEMENT_INDEX); + XX(NUM_SAMPLE_COUNTS); + XX(TEXTURE_IMMUTABLE_LEVELS); #undef XX } - return "[Unknown enum name]"; + return nullptr; +} + +void +WebGLContext::EnumName(GLenum glenum, nsACString* out_name) +{ + const char* name = EnumName(glenum); + if (name) { + *out_name = nsDependentCString(name); + } else { + nsPrintfCString enumAsHex("", glenum); + *out_name = enumAsHex; + } } bool diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextValidate.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextValidate.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLContextValidate.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLContextValidate.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -379,6 +379,118 @@ } /** + * Return true if pname is valid for GetSamplerParameter calls. + */ +bool +WebGLContext::ValidateSamplerParameterName(GLenum pname, const char* info) +{ + switch (pname) { + case LOCAL_GL_TEXTURE_MIN_FILTER: + case LOCAL_GL_TEXTURE_MAG_FILTER: + case LOCAL_GL_TEXTURE_WRAP_S: + case LOCAL_GL_TEXTURE_WRAP_T: + case LOCAL_GL_TEXTURE_WRAP_R: + case LOCAL_GL_TEXTURE_MIN_LOD: + case LOCAL_GL_TEXTURE_MAX_LOD: + case LOCAL_GL_TEXTURE_COMPARE_MODE: + case LOCAL_GL_TEXTURE_COMPARE_FUNC: + return true; + + default: + ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname)); + return false; + } +} + +/** + * Return true if pname and param are valid combination for SamplerParameter calls. + */ +bool +WebGLContext::ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info) +{ + const GLenum p = param.AsInt(); + + switch (pname) { + case LOCAL_GL_TEXTURE_MIN_FILTER: + switch (p) { + case LOCAL_GL_NEAREST: + case LOCAL_GL_LINEAR: + case LOCAL_GL_NEAREST_MIPMAP_NEAREST: + case LOCAL_GL_NEAREST_MIPMAP_LINEAR: + case LOCAL_GL_LINEAR_MIPMAP_NEAREST: + case LOCAL_GL_LINEAR_MIPMAP_LINEAR: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_MAG_FILTER: + switch (p) { + case LOCAL_GL_NEAREST: + case LOCAL_GL_LINEAR: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_WRAP_S: + case LOCAL_GL_TEXTURE_WRAP_T: + case LOCAL_GL_TEXTURE_WRAP_R: + switch (p) { + case LOCAL_GL_CLAMP_TO_EDGE: + case LOCAL_GL_REPEAT: + case LOCAL_GL_MIRRORED_REPEAT: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_MIN_LOD: + case LOCAL_GL_TEXTURE_MAX_LOD: + return true; + + case LOCAL_GL_TEXTURE_COMPARE_MODE: + switch (param.AsInt()) { + case LOCAL_GL_NONE: + case LOCAL_GL_COMPARE_REF_TO_TEXTURE: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_COMPARE_FUNC: + switch (p) { + case LOCAL_GL_LEQUAL: + case LOCAL_GL_GEQUAL: + case LOCAL_GL_LESS: + case LOCAL_GL_GREATER: + case LOCAL_GL_EQUAL: + case LOCAL_GL_NOTEQUAL: + case LOCAL_GL_ALWAYS: + case LOCAL_GL_NEVER: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + default: + ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname)); + return false; + } +} + + +/** * Return true if format is a valid texture image format for source, * taking into account enabled WebGL extensions. */ @@ -1529,7 +1641,7 @@ mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false); mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false); - mLoseContextOnMemoryPressure = Preferences::GetBool("webgl.lose-context-on-memory-preasure", false); + mLoseContextOnMemoryPressure = Preferences::GetBool("webgl.lose-context-on-memory-pressure", false); mCanLoseContextInForeground = Preferences::GetBool("webgl.can-lose-context-in-foreground", true); mRestoreWhenVisible = Preferences::GetBool("webgl.restore-context-when-visible", true); @@ -1718,8 +1830,7 @@ #ifdef XP_MACOSX if (gl->WorkAroundDriverBugs() && gl->Vendor() == gl::GLVendor::ATI && - nsCocoaFeatures::OSXVersionMajor() == 10 && - nsCocoaFeatures::OSXVersionMinor() < 9) + !nsCocoaFeatures::IsAtLeastVersion(10,9)) { // The Mac ATI driver, in all known OSX version up to and including 10.8, // renders points sprites upside-down. Apple bug 11778921 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLExtensionColorBufferFloat.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLExtensionColorBufferFloat.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLExtensionColorBufferFloat.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLExtensionColorBufferFloat.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -23,8 +23,13 @@ bool WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* context) { - return context->GL()->IsSupported(gl::GLFeature::renderbuffer_color_float) && - context->GL()->IsSupported(gl::GLFeature::frag_color_float); + gl::GLContext* gl = context->GL(); + + // ANGLE supports this, but doesn't have a way to advertize its support, + // since it's compliant with WEBGL_color_buffer_float's clamping, but not + // EXT_color_buffer_float. + return gl->IsSupported(gl::GLFeature::renderbuffer_color_float) || + gl->IsANGLE(); } IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -23,8 +23,10 @@ bool WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* context) { - return context->GL()->IsSupported(gl::GLFeature::renderbuffer_color_half_float) && - context->GL()->IsSupported(gl::GLFeature::frag_color_float); + gl::GLContext* gl = context->GL(); + + // ANGLE doesn't support ReadPixels from a RGBA16F with RGBA/FLOAT. + return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float); } IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLFramebuffer.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLFramebuffer.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLFramebuffer.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLFramebuffer.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -26,16 +26,14 @@ return dom::WebGLFramebufferBinding::Wrap(cx, this); } -WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context) - : WebGLBindableName() +WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context, GLuint fbo) + : WebGLBindableName(fbo) , WebGLContextBoundObject(context) , mStatus(0) , mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT) , mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT) , mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { - mContext->MakeContextCurrent(); - mContext->gl->fGenFramebuffers(1, &mGLName); mContext->mFramebuffers.insertBack(this); mColorAttachments.SetLength(1); @@ -286,6 +284,36 @@ } bool +WebGLContext::IsFormatValidForFB(GLenum sizedFormat) const +{ + switch (sizedFormat) { + case LOCAL_GL_ALPHA8: + case LOCAL_GL_LUMINANCE8: + case LOCAL_GL_LUMINANCE8_ALPHA8: + case LOCAL_GL_RGB8: + case LOCAL_GL_RGBA8: + case LOCAL_GL_RGB565: + case LOCAL_GL_RGB5_A1: + case LOCAL_GL_RGBA4: + return true; + + case LOCAL_GL_SRGB8: + case LOCAL_GL_SRGB8_ALPHA8_EXT: + return IsExtensionEnabled(WebGLExtensionID::EXT_sRGB); + + case LOCAL_GL_RGB32F: + case LOCAL_GL_RGBA32F: + return IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float); + + case LOCAL_GL_RGB16F: + case LOCAL_GL_RGBA16F: + return IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float); + } + + return false; +} + +bool WebGLFramebuffer::Attachment::IsComplete() const { if (!HasImage()) @@ -303,23 +331,24 @@ MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel)); const WebGLTexture::ImageInfo& imageInfo = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel); - GLenum internalformat = imageInfo.EffectiveInternalFormat().get(); + GLenum sizedFormat = imageInfo.EffectiveInternalFormat().get(); if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) - return IsValidFBOTextureDepthFormat(internalformat); + return IsValidFBOTextureDepthFormat(sizedFormat); if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) return false; // Textures can't have the correct format for stencil buffers if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { - return IsValidFBOTextureDepthStencilFormat(internalformat); + return IsValidFBOTextureDepthStencilFormat(sizedFormat); } if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 && mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 + WebGLContext::kMaxColorAttachments)) { - return IsValidFBOTextureColorFormat(internalformat); + WebGLContext* webgl = Texture()->Context(); + return webgl->IsFormatValidForFB(sizedFormat); } MOZ_ASSERT(false, "Invalid WebGL attachment point?"); return false; @@ -341,7 +370,8 @@ mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 + WebGLContext::kMaxColorAttachments)) { - return IsValidFBORenderbufferColorFormat(internalFormat); + WebGLContext* webgl = Renderbuffer()->Context(); + return webgl->IsFormatValidForFB(internalFormat); } MOZ_ASSERT(false, "Invalid WebGL attachment point?"); return false; @@ -375,7 +405,7 @@ MOZ_ASSERT(HasImage()); if (Texture()) { - MOZ_ASSERT(gl == Texture()->Context()->gl); + MOZ_ASSERT(gl == Texture()->Context()->GL()); const GLenum imageTarget = ImageTarget().get(); const GLint mipLevel = MipLevel(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLFramebuffer.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLFramebuffer.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLFramebuffer.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLFramebuffer.h 2014-11-26 21:45:57.000000000 +0000 @@ -34,7 +34,7 @@ public: MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLFramebuffer) - explicit WebGLFramebuffer(WebGLContext* context); + explicit WebGLFramebuffer(WebGLContext* context, GLuint fbo); struct Attachment { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLQuery.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLQuery.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLQuery.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLQuery.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -3,16 +3,18 @@ * 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/. */ -#include "WebGLContext.h" -#include "GLContext.h" #include "WebGLQuery.h" + +#include "GLContext.h" +#include "WebGLContext.h" #include "mozilla/dom/WebGL2RenderingContextBinding.h" #include "nsContentUtils.h" using namespace mozilla; JSObject* -WebGLQuery::WrapObject(JSContext *cx) { +WebGLQuery::WrapObject(JSContext* cx) +{ return dom::WebGLQueryBinding::Wrap(cx, this); } @@ -27,15 +29,18 @@ mContext->gl->fGenQueries(1, &mGLName); } -void WebGLQuery::Delete() { +void +WebGLQuery::Delete() +{ mContext->MakeContextCurrent(); mContext->gl->fDeleteQueries(1, &mGLName); LinkedListElement::removeFrom(mContext->mQueries); } -bool WebGLQuery::IsActive() const +bool +WebGLQuery::IsActive() const { - WebGLRefPtr* targetSlot = mContext->GetQueryTargetSlot(mType, "WebGLQuery::IsActive()"); + WebGLRefPtr* targetSlot = mContext->GetQueryTargetSlot(mType); MOZ_ASSERT(targetSlot, "unknown query object's type"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLQuery.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLQuery.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLQuery.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLQuery.h 2014-11-26 21:45:57.000000000 +0000 @@ -73,7 +73,7 @@ // ------------------------------------------------------------------------- // FRIENDSHIPS - friend class WebGLContext; + friend class WebGL2Context; }; } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLRenderbuffer.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLRenderbuffer.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLRenderbuffer.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLRenderbuffer.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -42,8 +42,8 @@ return dom::WebGLRenderbufferBinding::Wrap(cx, this); } -WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext *context) - : WebGLBindableName() +WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* context) + : WebGLBindable() , WebGLContextBoundObject(context) , mPrimaryRB(0) , mSecondaryRB(0) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLRenderbuffer.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLRenderbuffer.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLRenderbuffer.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLRenderbuffer.h 2014-11-26 21:45:57.000000000 +0000 @@ -18,7 +18,7 @@ class WebGLRenderbuffer MOZ_FINAL : public nsWrapperCache - , public WebGLBindableName + , public WebGLBindable , public WebGLRefCountedObject , public LinkedListElement , public WebGLRectangleObject diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLSampler.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLSampler.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLSampler.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLSampler.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -12,32 +12,36 @@ using namespace mozilla; -WebGLSampler::WebGLSampler(WebGLContext* context) - : WebGLContextBoundObject(context) +WebGLSampler::WebGLSampler(WebGLContext* context, GLuint sampler) + : WebGLBindableName(sampler), + WebGLContextBoundObject(context) { - MOZ_CRASH("Not Implemented."); + mContext->mSamplers.insertBack(this); } WebGLSampler::~WebGLSampler() -{} +{ + DeleteOnce(); +} void WebGLSampler::Delete() { - MOZ_CRASH("Not Implemented."); + mContext->MakeContextCurrent(); + mContext->gl->fDeleteSamplers(1, &mGLName); + + removeFrom(mContext->mSamplers); } WebGLContext* WebGLSampler::GetParentObject() const { - MOZ_CRASH("Not Implemented."); - return nullptr; + return Context(); } JSObject* WebGLSampler::WrapObject(JSContext* cx) { - MOZ_CRASH("Not Implemented."); return dom::WebGLSamplerBinding::Wrap(cx, this); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLSampler.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLSampler.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLSampler.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLSampler.h 2014-11-26 21:45:57.000000000 +0000 @@ -3,8 +3,8 @@ * 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/. */ -#ifndef WEBGL2SAMPLER_H_ -#define WEBGL2SAMPLER_H_ +#ifndef WEBGLSAMPLER_H_ +#define WEBGLSAMPLER_H_ #include "WebGLBindableName.h" #include "WebGLObjectModel.h" @@ -16,8 +16,8 @@ namespace mozilla { class WebGLSampler MOZ_FINAL - : public WebGLBindableName - , public nsWrapperCache + : public nsWrapperCache + , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -26,13 +26,15 @@ public: - explicit WebGLSampler(WebGLContext* aContext); + explicit WebGLSampler(WebGLContext* aContext, GLuint sampler); void Delete(); WebGLContext* GetParentObject() const; virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; +private: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler) @@ -43,4 +45,4 @@ } // namespace mozilla -#endif // !WEBGL2SAMPLER_H_ +#endif // !WEBGLSAMPLER_H_ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTexture.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTexture.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTexture.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTexture.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -19,12 +19,12 @@ using namespace mozilla; JSObject* -WebGLTexture::WrapObject(JSContext *cx) { +WebGLTexture::WrapObject(JSContext* cx) { return dom::WebGLTextureBinding::Wrap(cx, this); } -WebGLTexture::WebGLTexture(WebGLContext *context) - : WebGLBindableName() +WebGLTexture::WebGLTexture(WebGLContext* context, GLuint tex) + : WebGLBindableName(tex) , WebGLContextBoundObject(context) , mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR) , mMagFilter(LOCAL_GL_LINEAR) @@ -38,8 +38,6 @@ , mMaxMipmapLevel(1000) , mFakeBlackStatus(WebGLTextureFakeBlackStatus::IncompleteTexture) { - mContext->MakeContextCurrent(); - mContext->gl->fGenTextures(1, &mGLName); mContext->mTextures.insertBack(this); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTexture.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTexture.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTexture.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTexture.h 2014-11-26 21:45:57.000000000 +0000 @@ -38,7 +38,7 @@ , public WebGLFramebufferAttachable { public: - explicit WebGLTexture(WebGLContext* aContext); + explicit WebGLTexture(WebGLContext* aContext, GLuint tex); void Delete(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTransformFeedback.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTransformFeedback.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTransformFeedback.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTransformFeedback.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -13,7 +13,8 @@ using namespace mozilla; WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* context) - : WebGLContextBoundObject(context) + : WebGLBindableName(0) + , WebGLContextBoundObject(context) { MOZ_CRASH("Not Implemented."); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTransformFeedback.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTransformFeedback.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLTransformFeedback.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLTransformFeedback.h 2014-11-26 21:45:57.000000000 +0000 @@ -16,8 +16,8 @@ namespace mozilla { class WebGLTransformFeedback MOZ_FINAL - : public WebGLBindableName - , public nsWrapperCache + : public nsWrapperCache + , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLUniformInfo.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLUniformInfo.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLUniformInfo.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLUniformInfo.h 2014-11-26 21:45:57.000000000 +0000 @@ -21,27 +21,53 @@ int ElementSize() const { switch (type) { - case LOCAL_GL_INT: case LOCAL_GL_FLOAT: + case LOCAL_GL_INT: + case LOCAL_GL_UNSIGNED_INT: case LOCAL_GL_BOOL: case LOCAL_GL_SAMPLER_2D: + case LOCAL_GL_SAMPLER_3D: case LOCAL_GL_SAMPLER_CUBE: + case LOCAL_GL_SAMPLER_2D_SHADOW: + case LOCAL_GL_SAMPLER_2D_ARRAY: + case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW: + case LOCAL_GL_SAMPLER_CUBE_SHADOW: + case LOCAL_GL_INT_SAMPLER_2D: + case LOCAL_GL_INT_SAMPLER_3D: + case LOCAL_GL_INT_SAMPLER_CUBE: + case LOCAL_GL_INT_SAMPLER_2D_ARRAY: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return 1; - case LOCAL_GL_INT_VEC2: case LOCAL_GL_FLOAT_VEC2: + case LOCAL_GL_INT_VEC2: + case LOCAL_GL_UNSIGNED_INT_VEC2: case LOCAL_GL_BOOL_VEC2: return 2; - case LOCAL_GL_INT_VEC3: case LOCAL_GL_FLOAT_VEC3: + case LOCAL_GL_INT_VEC3: + case LOCAL_GL_UNSIGNED_INT_VEC3: case LOCAL_GL_BOOL_VEC3: return 3; - case LOCAL_GL_INT_VEC4: case LOCAL_GL_FLOAT_VEC4: + case LOCAL_GL_INT_VEC4: + case LOCAL_GL_UNSIGNED_INT_VEC4: case LOCAL_GL_BOOL_VEC4: case LOCAL_GL_FLOAT_MAT2: return 4; + case LOCAL_GL_FLOAT_MAT2x3: + case LOCAL_GL_FLOAT_MAT3x2: + return 6; + case LOCAL_GL_FLOAT_MAT2x4: + case LOCAL_GL_FLOAT_MAT4x2: + return 8; case LOCAL_GL_FLOAT_MAT3: return 9; + case LOCAL_GL_FLOAT_MAT3x4: + case LOCAL_GL_FLOAT_MAT4x3: + return 12; case LOCAL_GL_FLOAT_MAT4: return 16; default: diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLVertexArray.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLVertexArray.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLVertexArray.cpp 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLVertexArray.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -20,8 +20,9 @@ } WebGLVertexArray::WebGLVertexArray(WebGLContext* context) - : WebGLBindableName() + : WebGLBindable() , WebGLContextBoundObject(context) + , mGLName(0) { context->mVertexArrays.insertBack(this); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLVertexArray.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLVertexArray.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/canvas/WebGLVertexArray.h 2014-11-14 09:37:22.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/canvas/WebGLVertexArray.h 2014-11-26 21:45:57.000000000 +0000 @@ -22,7 +22,7 @@ class WebGLVertexArray : public nsWrapperCache - , public WebGLBindableName + , public WebGLBindable , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -61,6 +61,8 @@ // ------------------------------------------------------------------------- // MEMBER FUNCTIONS + GLuint GLName() const { return mGLName; } + void EnsureAttrib(GLuint index); bool HasAttrib(GLuint index) { return index < mAttribs.Length(); @@ -82,6 +84,7 @@ // ------------------------------------------------------------------------- // MEMBERS + GLuint mGLName; nsTArray mAttribs; WebGLRefPtr mElementArrayBuffer; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/CellBroadcastMessage.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/CellBroadcastMessage.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/CellBroadcastMessage.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/CellBroadcastMessage.cpp 2014-11-26 21:45:57.000000000 +0000 @@ -83,12 +83,14 @@ aEtwsPopup) : nullptr) { - if (aGsmGeographicalScope < nsICellBroadcastService::GSM_GEOGRAPHICAL_SCOPE_INVALID) { + if (aGsmGeographicalScope < + static_cast(CellBroadcastGsmGeographicalScope::EndGuard_)) { mGsmGeographicalScope.SetValue( ToWebidlEnum(aGsmGeographicalScope)); } - if (aMessageClass < nsICellBroadcastService::GSM_MESSAGE_CLASS_INVALID) { + if (aMessageClass < + static_cast(CellBroadcastMessageClass::EndGuard_)) { mMessageClass.SetValue( ToWebidlEnum(aMessageClass)); } @@ -134,7 +136,8 @@ , mEmergencyUserAlert(aEmergencyUserAlert) , mPopup(aPopup) { - if (aWarningType < nsICellBroadcastService::GSM_ETWS_WARNING_INVALID) { + if (aWarningType < + static_cast(CellBroadcastEtwsWarningType::EndGuard_)) { mWarningType.SetValue( ToWebidlEnum(aWarningType)); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/gonk/CellBroadcastService.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/gonk/CellBroadcastService.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/gonk/CellBroadcastService.js 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/gonk/CellBroadcastService.js 2014-11-26 21:45:57.000000000 +0000 @@ -20,9 +20,9 @@ const kSettingsCellBroadcastDisabled = "ril.cellbroadcast.disabled"; const kSettingsCellBroadcastSearchList = "ril.cellbroadcast.searchlist"; -XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger", - "@mozilla.org/system-message-internal;1", - "nsISystemMessagesInternal"); +XPCOMUtils.defineLazyServiceGetter(this, "gCellbroadcastMessenger", + "@mozilla.org/ril/system-messenger-helper;1", + "nsICellbroadcastMessenger"); XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService", "@mozilla.org/settingsService;1", @@ -112,24 +112,6 @@ } catch (e) {} }, - _convertCbGsmGeographicalScope: function(aGeographicalScope) { - return (aGeographicalScope >= Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID) - ? null - : RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[aGeographicalScope]; - }, - - _convertCbMessageClass: function(aMessageClass) { - return (aMessageClass >= Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS) - ? null - : RIL.GECKO_SMS_MESSAGE_CLASSES[aMessageClass]; - }, - - _convertCbEtwsWarningType: function(aWarningType) { - return (aWarningType >= Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID) - ? null - : RIL.CB_ETWS_WARNING_TYPE_NAMES[aWarningType]; - }, - _retrieveSettingValueByClient: function(aClientId, aSettings) { return Array.isArray(aSettings) ? aSettings[aClientId] : aSettings; }, @@ -236,38 +218,19 @@ aEtwsEmergencyUserAlert, aEtwsPopup) { // Broadcast CBS System message - // Align the same layout to MozCellBroadcastMessage - let systemMessage = { - serviceId: aServiceId, - gsmGeographicalScope: this._convertCbGsmGeographicalScope(aGsmGeographicalScope), - messageCode: aMessageCode, - messageId: aMessageId, - language: aLanguage, - body: aBody, - messageClass: this._convertCbMessageClass(aMessageClass), - timestamp: aTimestamp, - cdmaServiceCategory: null, - etws: null - }; - - if (aHasEtwsInfo) { - systemMessage.etws = { - warningType: this._convertCbEtwsWarningType(aEtwsWarningType), - emergencyUserAlert: aEtwsEmergencyUserAlert, - popup: aEtwsPopup - }; - } - - if (aCdmaServiceCategory != - Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID) { - systemMessage.cdmaServiceCategory = aCdmaServiceCategory; - } - - if (DEBUG) { - debug("CBS system message to be broadcasted: " + JSON.stringify(systemMessage)); - } - - gSystemMessenger.broadcastMessage("cellbroadcast-received", systemMessage); + gCellbroadcastMessenger.notifyCbMessageReceived(aServiceId, + aGsmGeographicalScope, + aMessageCode, + aMessageId, + aLanguage, + aBody, + aMessageClass, + aTimestamp, + aCdmaServiceCategory, + aHasEtwsInfo, + aEtwsWarningType, + aEtwsEmergencyUserAlert, + aEtwsPopup); // Notify received message to registered listener for (let listener of this._listeners) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/interfaces/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/interfaces/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/interfaces/moz.build 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/interfaces/moz.build 2014-11-26 21:45:57.000000000 +0000 @@ -10,6 +10,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: XPIDL_SOURCES += [ + 'nsICellbroadcastMessenger.idl', 'nsIGonkCellBroadcastService.idl', ] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/interfaces/nsICellbroadcastMessenger.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/interfaces/nsICellbroadcastMessenger.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/interfaces/nsICellbroadcastMessenger.idl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/interfaces/nsICellbroadcastMessenger.idl 2014-11-26 21:45:57.000000000 +0000 @@ -0,0 +1,55 @@ +/* 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/. */ + +#include "domstubs.idl" +#include "nsISupports.idl" + +[scriptable, uuid(47764f4a-5b3f-11e4-a2ec-4b99529b9288)] +interface nsICellbroadcastMessenger : nsISupports +{ + /** + * To broadcast 'cellbroadcast-received' system message. + * + * @param aServiceId + * The ID of Service where this info is notified from. + * @param aGsmGeographicalScope + * @See nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_*. + * @param aMessageCode + * The Message Code differentiates between messages from the same + * source and type (e.g., with the same Message Identifier). + * @param aMessageId + * Source and type of the message which is coded in binary. + * @param aLanguage + * ISO-639-1 language code for this message. Null if unspecified. + * @param aBody + * Text message carried by the message. + * @param aMessageClass + * @See nsICellBroadcastService.GSM_MESSAGE_CLASS_*. + * @param aTimestamp + * System time stamp at receival. + * @param aCdmaServiceCategory + * CDMA Service Category. + * @param aHasEtwsInfo + * True if ETWS Info is included in this message. + * @param aEtwsWarningType + * @See nsICellBroadcastService.GSM_ETWS_WARNING_*. + * @param aEtwsEmergencyUserAlert + * True if Emergency user alert indication is set. + * @param aEtwsPopup + * True if Message popup indication is set. + */ + void notifyCbMessageReceived(in unsigned long aServiceId, + in unsigned long aGsmGeographicalScope, + in unsigned short aMessageCode, + in unsigned short aMessageId, + in DOMString aLanguage, + in DOMString aBody, + in unsigned long aMessageClass, + in DOMTimeStamp aTimestamp, + in unsigned long aCdmaServiceCategory, + in boolean aHasEtwsInfo, + in unsigned long aEtwsWarningType, + in boolean aEtwsEmergencyUserAlert, + in boolean aEtwsPopup); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/interfaces/nsICellBroadcastService.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/interfaces/nsICellBroadcastService.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/cellbroadcast/interfaces/nsICellBroadcastService.idl 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/cellbroadcast/interfaces/nsICellBroadcastService.idl 2014-11-26 21:45:57.000000000 +0000 @@ -36,7 +36,7 @@ /** * XPCOM component that provides the cell broadcast information. */ -[scriptable, uuid(eed283f6-44a8-11e4-b364-afb894b7a283)] +[scriptable, uuid(906cda5a-6b18-11e4-973b-5ff3fc075b6b)] interface nsICellBroadcastService : nsISupports { /** @@ -47,11 +47,13 @@ const unsigned short GSM_GEOGRAPHICAL_SCOPE_PLMN = 1; const unsigned short GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA = 2; const unsigned short GSM_GEOGRAPHICAL_SCOPE_CELL = 3; - const unsigned short GSM_GEOGRAPHICAL_SCOPE_INVALID = 4; + const unsigned short GSM_GEOGRAPHICAL_SCOPE_INVALID = 0xFFFF; /** * Constant definitions of predefined GSM Message Class * See 3GPP TS 23.038 clause 5 CBS Data Coding Scheme + * + * Set to GSM_MESSAGE_CLASS_NORMAL if no message class is specified. */ const unsigned short GSM_MESSAGE_CLASS_0 = 0; const unsigned short GSM_MESSAGE_CLASS_1 = 1; @@ -60,7 +62,6 @@ const unsigned short GSM_MESSAGE_CLASS_USER_1 = 4; const unsigned short GSM_MESSAGE_CLASS_USER_2 = 5; const unsigned short GSM_MESSAGE_CLASS_NORMAL = 6; - const unsigned short GSM_MESSAGE_CLASS_INVALID = 7; /** * Constant definitions of predefined GSM ETWS Warning Types @@ -71,7 +72,7 @@ const unsigned short GSM_ETWS_WARNING_EARTHQUAKE_TSUNAMI = 2; const unsigned short GSM_ETWS_WARNING_TEST = 3; const unsigned short GSM_ETWS_WARNING_OTHER = 4; - const unsigned short GSM_ETWS_WARNING_INVALID = 5; + const unsigned short GSM_ETWS_WARNING_INVALID = 0xFFFF; /** * Attribute CdmaServiceCategory is only valid in CDMA network. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextDecoder.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextDecoder.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextDecoder.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextDecoder.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -1,10 +1,13 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ #include "mozilla/dom/TextDecoder.h" #include "mozilla/dom/EncodingUtils.h" +#include "mozilla/dom/UnionTypes.h" #include "nsContentUtils.h" +#include namespace mozilla { namespace dom { @@ -94,6 +97,40 @@ } void +TextDecoder::Decode(const Optional& aBuffer, + const TextDecodeOptions& aOptions, + nsAString& aOutDecodedString, + ErrorResult& aRv) +{ + if (!aBuffer.WasPassed()) { + Decode(nullptr, 0, aOptions.mStream, aOutDecodedString, aRv); + return; + } + const ArrayBufferViewOrArrayBuffer& buf = aBuffer.Value(); + uint8_t* data; + uint32_t length; + if (buf.IsArrayBufferView()) { + buf.GetAsArrayBufferView().ComputeLengthAndData(); + data = buf.GetAsArrayBufferView().Data(); + length = buf.GetAsArrayBufferView().Length(); + } else { + MOZ_ASSERT(buf.IsArrayBuffer()); + buf.GetAsArrayBuffer().ComputeLengthAndData(); + data = buf.GetAsArrayBuffer().Data(); + length = buf.GetAsArrayBuffer().Length(); + } + // The other Decode signature takes a signed int, because that's + // what nsIUnicodeDecoder::Convert takes as the length. Throw if + // our length is too big. + if (length > INT32_MAX) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return; + } + Decode(reinterpret_cast(data), length, aOptions.mStream, + aOutDecodedString, aRv); +} + +void TextDecoder::GetEncoding(nsAString& aEncoding) { CopyASCIItoUTF16(mEncoding, aEncoding); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextDecoder.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextDecoder.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextDecoder.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextDecoder.h 2014-11-26 21:45:58.000000000 +0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ @@ -16,6 +17,8 @@ namespace dom { +class ArrayBufferViewOrArrayBuffer; + class TextDecoder MOZ_FINAL : public NonRefcountedDOMObject { @@ -98,18 +101,13 @@ const bool aStream, nsAString& aOutDecodedString, ErrorResult& aRv); - void Decode(nsAString& aOutDecodedString, - ErrorResult& aRv) { - Decode(nullptr, 0, false, aOutDecodedString, aRv); - } - - void Decode(const ArrayBufferView& aView, + void Decode(const Optional& aBuffer, const TextDecodeOptions& aOptions, nsAString& aOutDecodedString, - ErrorResult& aRv) { - aView.ComputeLengthAndData(); - Decode(reinterpret_cast(aView.Data()), aView.Length(), - aOptions.mStream, aOutDecodedString, aRv); + ErrorResult& aRv); + + bool Fatal() const { + return mFatal; } private: diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextEncoder.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextEncoder.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextEncoder.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextEncoder.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ @@ -38,8 +39,7 @@ TextEncoder::Encode(JSContext* aCx, JS::Handle aObj, const nsAString& aString, - const bool aStream, - JS::MutableHandle aRetval, + JS::MutableHandle aRetval, ErrorResult& aRv) { // Run the steps of the encoding algorithm. @@ -63,14 +63,11 @@ int32_t dstLen = maxLen; rv = mEncoder->Convert(data, &srcLen, buf, &dstLen); - // If the internal streaming flag is not set, then reset - // the encoding algorithm state to the default values for encoding. - if (!aStream) { - int32_t finishLen = maxLen - dstLen; - rv = mEncoder->Finish(buf + dstLen, &finishLen); - if (NS_SUCCEEDED(rv)) { - dstLen += finishLen; - } + // Now reset the encoding algorithm state to the default values for encoding. + int32_t finishLen = maxLen - dstLen; + rv = mEncoder->Finish(buf + dstLen, &finishLen); + if (NS_SUCCEEDED(rv)) { + dstLen += finishLen; } JSObject* outView = nullptr; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextEncoder.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextEncoder.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/encoding/TextEncoder.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/encoding/TextEncoder.h 2014-11-26 21:45:58.000000000 +0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ @@ -46,15 +47,6 @@ return TextEncoderBinding::Wrap(aCx, this, aTookOwnership); } - void Encode(JSContext* aCx, - JS::Handle aObj, - const nsAString& aString, - const TextEncodeOptions& aOptions, - JS::MutableHandle aRetval, - ErrorResult& aRv) { - TextEncoder::Encode(aCx, aObj, aString, aOptions.mStream, aRetval, aRv); - } - protected: /** @@ -82,20 +74,14 @@ * @param aCx Javascript context. * @param aObj the wrapper of the TextEncoder * @param aString utf-16 code units to be encoded. - * @param aOptions Streaming option. Initialised by default to false. - * If the streaming option is false, then the encoding - * algorithm state will get reset. If set to true then - * the previous encoding is reused/continued. * @return JSObject* The Uint8Array wrapped in a JS object. Returned via * the aRetval out param. */ void Encode(JSContext* aCx, - JS::Handle aObj, - const nsAString& aString, - const bool aStream, - JS::MutableHandle aRetval, - ErrorResult& aRv); - + JS::Handle aObj, + const nsAString& aString, + JS::MutableHandle aRetval, + ErrorResult& aRv); private: nsCString mEncoding; nsCOMPtr mEncoder; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/ContentEventHandler.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/ContentEventHandler.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/ContentEventHandler.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/ContentEventHandler.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -604,6 +604,23 @@ LINE_BREAK_TYPE_NATIVE : LINE_BREAK_TYPE_XP; } +// Similar to nsFrameSelection::GetFrameForNodeOffset, +// but this is more flexible for OnQueryTextRect to use +static nsresult GetFrameForTextRect(nsINode* aNode, + int32_t aNodeOffset, + bool aHint, + nsIFrame** aReturnFrame) +{ + NS_ENSURE_TRUE(aNode && aNode->IsNodeOfType(nsINode::eCONTENT), + NS_ERROR_UNEXPECTED); + nsIContent* content = static_cast(aNode); + nsIFrame* frame = content->GetPrimaryFrame(); + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); + int32_t childNodeOffset = 0; + return frame->GetChildFrameContainingOffset(aNodeOffset, aHint, + &childNodeOffset, aReturnFrame); +} + nsresult ContentEventHandler::OnQuerySelectedText(WidgetQueryContentEvent* aEvent) { @@ -646,6 +663,14 @@ NS_ENSURE_SUCCESS(rv, rv); } + nsIFrame* frame = nullptr; + rv = GetFrameForTextRect(focusNode, focusOffset, true, &frame); + if (NS_SUCCEEDED(rv) && frame) { + aEvent->mReply.mWritingMode = frame->GetWritingMode(); + } else { + aEvent->mReply.mWritingMode = WritingMode(); + } + aEvent->mSucceeded = true; return NS_OK; } @@ -697,23 +722,6 @@ return node; } -// Similar to nsFrameSelection::GetFrameForNodeOffset, -// but this is more flexible for OnQueryTextRect to use -static nsresult GetFrameForTextRect(nsINode* aNode, - int32_t aNodeOffset, - bool aHint, - nsIFrame** aReturnFrame) -{ - NS_ENSURE_TRUE(aNode && aNode->IsNodeOfType(nsINode::eCONTENT), - NS_ERROR_UNEXPECTED); - nsIContent* content = static_cast(aNode); - nsIFrame* frame = content->GetPrimaryFrame(); - NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); - int32_t childNodeOffset = 0; - return frame->GetChildFrameContainingOffset(aNodeOffset, aHint, - &childNodeOffset, aReturnFrame); -} - nsresult ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/Event.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/Event.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/Event.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/Event.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -886,7 +886,8 @@ LayoutDeviceIntPoint offset = aPoint + LayoutDeviceIntPoint::FromUntyped(guiEvent->widget->WidgetToScreenOffset()); - nscoord factor = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel(); + nscoord factor = + aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor), nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor)); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/EventDispatcher.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/EventDispatcher.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/EventDispatcher.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/EventDispatcher.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -32,6 +32,12 @@ #include "mozilla/TouchEvents.h" #include "mozilla/unused.h" +#ifdef MOZ_TASK_TRACER +#include "GeckoTaskTracer.h" +#include "mozilla/dom/Element.h" +using namespace mozilla::tasktracer; +#endif + namespace mozilla { using namespace dom; @@ -407,6 +413,27 @@ NS_ENSURE_TRUE(aEvent->message || !aDOMEvent || aTargets, NS_ERROR_DOM_INVALID_STATE_ERR); +#ifdef MOZ_TASK_TRACER + { + if (aDOMEvent) { + nsAutoString eventType; + aDOMEvent->GetType(eventType); + + nsCOMPtr element = do_QueryInterface(aTarget); + nsAutoString elementId; + nsAutoString elementTagName; + if (element) { + element->GetId(elementId); + element->GetTagName(elementTagName); + } + AddLabel("Event [%s] dispatched at target [id:%s tag:%s]", + NS_ConvertUTF16toUTF8(eventType).get(), + NS_ConvertUTF16toUTF8(elementId).get(), + NS_ConvertUTF16toUTF8(elementTagName).get()); + } + } +#endif + nsCOMPtr target = do_QueryInterface(aTarget); bool retargeted = false; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/EventListenerManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/EventListenerManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/EventListenerManager.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/EventListenerManager.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -1012,6 +1012,26 @@ return docShell; } +class EventTimelineMarker : public nsDocShell::TimelineMarker +{ +public: + EventTimelineMarker(nsDocShell* aDocShell, TracingMetadata aMetaData, + uint16_t aPhase, const nsAString& aCause) + : nsDocShell::TimelineMarker(aDocShell, "DOMEvent", aMetaData, aCause) + , mPhase(aPhase) + { + } + + virtual void AddDetails(mozilla::dom::ProfileTimelineMarker& aMarker) + { + aMarker.mType.Construct(GetCause()); + aMarker.mEventPhase.Construct(mPhase); + } + +private: + uint16_t mPhase; +}; + /** * Causes a check for event listeners and processing by them if they exist. * @param an event listener @@ -1066,13 +1086,24 @@ // Maybe add a marker to the docshell's timeline, but only // bother with all the logic if some docshell is recording. nsCOMPtr docShell; + bool isTimelineRecording = false; if (mIsMainThreadELM && nsDocShell::gProfileTimelineRecordingsCount > 0 && listener->mListenerType != Listener::eNativeListener) { docShell = GetDocShellForTarget(); if (docShell) { + docShell->GetRecordProfileTimelineMarkers(&isTimelineRecording); + } + if (isTimelineRecording) { nsDocShell* ds = static_cast(docShell.get()); - ds->AddProfileTimelineMarker("DOMEvent", TRACING_INTERVAL_START); + nsAutoString typeStr; + (*aDOMEvent)->GetType(typeStr); + uint16_t phase; + (*aDOMEvent)->GetEventPhase(&phase); + mozilla::UniquePtr marker = + MakeUnique(ds, TRACING_INTERVAL_START, + phase, typeStr); + ds->AddProfileTimelineMarker(marker); } } @@ -1081,7 +1112,7 @@ aEvent->mFlags.mExceptionHasBeenRisen = true; } - if (docShell) { + if (isTimelineRecording) { nsDocShell* ds = static_cast(docShell.get()); ds->AddProfileTimelineMarker("DOMEvent", TRACING_INTERVAL_END); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/EventStateManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/EventStateManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/EventStateManager.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/EventStateManager.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -819,6 +819,8 @@ // through to compositionend handling case NS_COMPOSITION_END: case NS_COMPOSITION_CHANGE: + case NS_COMPOSITION_COMMIT_AS_IS: + case NS_COMPOSITION_COMMIT: { WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent(); if (IsTargetCrossProcess(compositionEvent)) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/IMEStateManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/IMEStateManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/IMEStateManager.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/IMEStateManager.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -143,6 +143,8 @@ return "NS_COMPOSITION_UPDATE"; case NS_COMPOSITION_CHANGE: return "NS_COMPOSITION_CHANGE"; + case NS_COMPOSITION_COMMIT_AS_IS: + return "NS_COMPOSITION_COMMIT_AS_IS"; default: return "unacceptable event message"; } @@ -943,7 +945,7 @@ // destroy the TextComposition with synthesized compositionend event. if ((!aIsSynthesized || composition->WasNativeCompositionEndEventDiscarded()) && - aCompositionEvent->message == NS_COMPOSITION_END) { + aCompositionEvent->CausesDOMCompositionEndEvent()) { TextCompositionArray::index_type i = sTextCompositions->IndexOf(aCompositionEvent->widget); if (i != TextCompositionArray::NoIndex) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/bug1096146_embedded.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/bug1096146_embedded.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/bug1096146_embedded.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/bug1096146_embedded.html 2014-11-26 21:45:58.000000000 +0000 @@ -0,0 +1,16 @@ + + + + Embedded iframe + + + + +

+

Top

+ +
+  
+

Bottom

+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/mochitest.ini 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/mochitest.ini 2014-11-26 21:45:58.000000000 +0000 @@ -176,3 +176,6 @@ bug989198_embedded.html bug989198_helper.js skip-if = buildapp == 'b2g' || e10s +[test_bug1096146.html] +support-files = + bug1096146_embedded.html diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/test_all_synthetic_events.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/test_all_synthetic_events.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/test_all_synthetic_events.html 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/test_all_synthetic_events.html 2014-11-26 21:45:58.000000000 +0000 @@ -80,6 +80,10 @@ return new CallGroupErrorEvent(aName, aProps); }, }, + CameraClosedEvent: { create: function (aName, aProps) { + return new CameraClosedEvent(aName, aProps); + }, + }, CameraConfigurationEvent: { create: function (aName, aProps) { return new CameraConfigurationEvent(aName, aProps); }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/test_bug1096146.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/test_bug1096146.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/test/test_bug1096146.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/test/test_bug1096146.html 2014-11-26 21:45:58.000000000 +0000 @@ -0,0 +1,170 @@ + + + + + + Test for Bug 1096146 + + + + + +Mozilla Bug 1096146 + +
+
+
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/TextComposition.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/TextComposition.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/TextComposition.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/TextComposition.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -62,31 +62,54 @@ } bool +TextComposition::IsValidStateForComposition(nsIWidget* aWidget) const +{ + return !Destroyed() && aWidget && !aWidget->Destroyed() && + mPresContext->GetPresShell() && + !mPresContext->GetPresShell()->IsDestroying(); +} + +bool TextComposition::MaybeDispatchCompositionUpdate( const WidgetCompositionEvent* aCompositionEvent) { - if (Destroyed()) { + if (!IsValidStateForComposition(aCompositionEvent->widget)) { return false; } if (mLastData == aCompositionEvent->mData) { return true; } + CloneAndDispatchAs(aCompositionEvent, NS_COMPOSITION_UPDATE); + return IsValidStateForComposition(aCompositionEvent->widget); +} - WidgetCompositionEvent compositionUpdate(aCompositionEvent->mFlags.mIsTrusted, - NS_COMPOSITION_UPDATE, - aCompositionEvent->widget); - compositionUpdate.time = aCompositionEvent->time; - compositionUpdate.timeStamp = aCompositionEvent->timeStamp; - compositionUpdate.mData = aCompositionEvent->mData; - compositionUpdate.mFlags.mIsSynthesizedForTests = +BaseEventFlags +TextComposition::CloneAndDispatchAs( + const WidgetCompositionEvent* aCompositionEvent, + uint32_t aMessage, + nsEventStatus* aStatus, + EventDispatchingCallback* aCallBack) +{ + MOZ_ASSERT(IsValidStateForComposition(aCompositionEvent->widget), + "Should be called only when it's safe to dispatch an event"); + + WidgetCompositionEvent compositionEvent(aCompositionEvent->mFlags.mIsTrusted, + aMessage, aCompositionEvent->widget); + compositionEvent.time = aCompositionEvent->time; + compositionEvent.timeStamp = aCompositionEvent->timeStamp; + compositionEvent.mData = aCompositionEvent->mData; + compositionEvent.mFlags.mIsSynthesizedForTests = aCompositionEvent->mFlags.mIsSynthesizedForTests; - nsEventStatus status = nsEventStatus_eConsumeNoDefault; - mLastData = compositionUpdate.mData; + nsEventStatus dummyStatus = nsEventStatus_eConsumeNoDefault; + nsEventStatus* status = aStatus ? aStatus : &dummyStatus; + if (aMessage == NS_COMPOSITION_UPDATE) { + mLastData = compositionEvent.mData; + } EventDispatcher::Dispatch(mNode, mPresContext, - &compositionUpdate, nullptr, &status, nullptr); - return !Destroyed(); + &compositionEvent, nullptr, status, aCallBack); + return compositionEvent.mFlags; } void @@ -103,7 +126,7 @@ // runnable event? However, even if we do so, it might make native IME // confused due to async modification. Especially when native IME is // TSF. - if (aCompositionEvent->message != NS_COMPOSITION_END) { + if (!aCompositionEvent->CausesDOMCompositionEndEvent()) { return; } @@ -117,7 +140,27 @@ EventDispatchingCallback* aCallBack, bool aIsSynthesized) { - if (Destroyed()) { + if (aCompositionEvent->message == NS_COMPOSITION_COMMIT_AS_IS) { + NS_ASSERTION(!aCompositionEvent->mRanges, + "mRanges of NS_COMPOSITION_COMMIT_AS_IS should be null"); + aCompositionEvent->mRanges = nullptr; + NS_ASSERTION(aCompositionEvent->mData.IsEmpty(), + "mData of NS_COMPOSITION_COMMIT_AS_IS should be empty string"); + if (mLastData == IDEOGRAPHIC_SPACE) { + // If the last data is an ideographic space (FullWidth space), it must be + // a placeholder character of some Chinese IME. So, committing with + // this data must not be expected by users. Let's use empty string. + aCompositionEvent->mData.Truncate(); + } else { + aCompositionEvent->mData = mLastData; + } + } else if (aCompositionEvent->message == NS_COMPOSITION_COMMIT) { + NS_ASSERTION(!aCompositionEvent->mRanges, + "mRanges of NS_COMPOSITION_COMMIT should be null"); + aCompositionEvent->mRanges = nullptr; + } + + if (!IsValidStateForComposition(aCompositionEvent->widget)) { *aStatus = nsEventStatus_eConsumeNoDefault; return; } @@ -149,6 +192,8 @@ switch (aCompositionEvent->message) { case NS_COMPOSITION_END: case NS_COMPOSITION_CHANGE: + case NS_COMPOSITION_COMMIT_AS_IS: + case NS_COMPOSITION_COMMIT: committingData = &aCompositionEvent->mData; break; default: @@ -166,32 +211,62 @@ } } - if (aCompositionEvent->message == NS_COMPOSITION_CHANGE) { + bool dispatchEvent = true; + bool dispatchDOMTextEvent = aCompositionEvent->CausesDOMTextEvent(); + + // When mIsComposing is false but the committing string is different from + // the last data (E.g., previous NS_COMPOSITION_CHANGE event made the + // composition string empty or didn't have clause information), we don't + // need to dispatch redundant DOM text event. + if (dispatchDOMTextEvent && + aCompositionEvent->message != NS_COMPOSITION_CHANGE && + !mIsComposing && mLastData == aCompositionEvent->mData) { + dispatchEvent = dispatchDOMTextEvent = false; + } + + if (dispatchDOMTextEvent) { if (!MaybeDispatchCompositionUpdate(aCompositionEvent)) { return; } } - EventDispatcher::Dispatch(mNode, mPresContext, - aCompositionEvent, nullptr, aStatus, aCallBack); + if (dispatchEvent) { + // If the composition event should cause a DOM text event, we should + // overwrite the event message as NS_COMPOSITION_CHANGE because due to + // the limitation of mapping between event messages and DOM event types, + // we cannot map multiple event messages to a DOM event type. + if (dispatchDOMTextEvent && + aCompositionEvent->message != NS_COMPOSITION_CHANGE) { + aCompositionEvent->mFlags = + CloneAndDispatchAs(aCompositionEvent, NS_COMPOSITION_CHANGE, + aStatus, aCallBack); + } else { + EventDispatcher::Dispatch(mNode, mPresContext, + aCompositionEvent, nullptr, aStatus, aCallBack); + } + } else { + *aStatus = nsEventStatus_eConsumeNoDefault; + } - if (NS_WARN_IF(Destroyed())) { + if (!IsValidStateForComposition(aCompositionEvent->widget)) { return; } // Emulate editor behavior of compositionchange event (DOM text event) handler // if no editor handles composition events. - if (aCompositionEvent->message == NS_COMPOSITION_CHANGE && !HasEditor()) { + if (dispatchDOMTextEvent && !HasEditor()) { EditorWillHandleCompositionChangeEvent(aCompositionEvent); EditorDidHandleCompositionChangeEvent(); } -#ifdef DEBUG - else if (aCompositionEvent->message == NS_COMPOSITION_END) { + if (aCompositionEvent->CausesDOMCompositionEndEvent()) { + // Dispatch a compositionend event if it's necessary. + if (aCompositionEvent->message != NS_COMPOSITION_END) { + CloneAndDispatchAs(aCompositionEvent, NS_COMPOSITION_END); + } MOZ_ASSERT(!mIsComposing, "Why is the editor still composing?"); MOZ_ASSERT(!HasEditor(), "Why does the editor still keep to hold this?"); } -#endif // #ifdef DEBUG // Notify composition update to widget if possible NotityUpdateComposition(aCompositionEvent); @@ -221,7 +296,7 @@ mCompositionStartOffset = 0; } mCompositionTargetOffset = mCompositionStartOffset; - } else if (aCompositionEvent->message == NS_COMPOSITION_CHANGE) { + } else if (aCompositionEvent->CausesDOMTextEvent()) { mCompositionTargetOffset = mCompositionStartOffset + aCompositionEvent->TargetClauseOffset(); } else { @@ -284,30 +359,16 @@ // dispatch the event. nsCOMPtr widget(aWidget); nsAutoString commitData(aDiscard ? EmptyString() : lastData); - bool changingData = lastData != commitData; - - WidgetCompositionEvent changeEvent(true, NS_COMPOSITION_CHANGE, widget); - changeEvent.mData = commitData; - changeEvent.mFlags.mIsSynthesizedForTests = true; - - MaybeDispatchCompositionUpdate(&changeEvent); - - // If changing the data or committing string isn't empty, we need to - // dispatch compositionchange event for setting the composition string - // without IME selection. - if (!Destroyed() && !widget->Destroyed() && - (changingData || !commitData.IsEmpty())) { - nsEventStatus status = nsEventStatus_eIgnore; - widget->DispatchEvent(&changeEvent, status); - } - - if (!Destroyed() && !widget->Destroyed()) { - nsEventStatus status = nsEventStatus_eIgnore; - WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget); - endEvent.mData = commitData; - endEvent.mFlags.mIsSynthesizedForTests = true; - widget->DispatchEvent(&endEvent, status); + bool isChanging = commitData != mLastData; + uint32_t message = + isChanging ? NS_COMPOSITION_COMMIT : NS_COMPOSITION_COMMIT_AS_IS; + WidgetCompositionEvent commitEvent(true, message, widget); + if (commitEvent.message == NS_COMPOSITION_COMMIT) { + commitEvent.mData = commitData; } + commitEvent.mFlags.mIsSynthesizedForTests = true; + nsEventStatus status = nsEventStatus_eIgnore; + widget->DispatchEvent(&commitEvent, status); } } @@ -320,15 +381,12 @@ // Otherwise, synthesize the commit in content. nsAutoString data(aDiscard ? EmptyString() : lastData); - // If the last composition string and new data are different, we need to - // dispatch compositionchange event for removing IME selection. However, if - // the commit string is empty string and it's not changed from the last data, - // we don't need to dispatch compositionchange event. - if (lastData != data || !data.IsEmpty()) { - DispatchCompositionEventRunnable(NS_COMPOSITION_CHANGE, data, true); + if (data == mLastData) { + DispatchCompositionEventRunnable(NS_COMPOSITION_COMMIT_AS_IS, EmptyString(), + true); + } else { + DispatchCompositionEventRunnable(NS_COMPOSITION_COMMIT, data, true); } - DispatchCompositionEventRunnable(NS_COMPOSITION_END, data, true); - return NS_OK; } @@ -411,22 +469,17 @@ NS_IMETHODIMP TextComposition::CompositionEventDispatcher::Run() { - nsRefPtr presContext = mTextComposition->mPresContext; - if (!presContext || !presContext->GetPresShell() || - presContext->GetPresShell()->IsDestroying()) { - return NS_OK; // cannot dispatch any events anymore - } - // The widget can be different from the widget which has dispatched // composition events because GetWidget() returns a widget which is proper // for calling NotifyIME(). However, this must no be problem since both // widget should share native IME context. Therefore, even if an event // handler uses the widget for requesting IME to commit or cancel, it works. nsCOMPtr widget(mTextComposition->GetWidget()); - if (NS_WARN_IF(!widget)) { + if (!mTextComposition->IsValidStateForComposition(widget)) { return NS_OK; // cannot dispatch any events anymore } + nsRefPtr presContext = mTextComposition->mPresContext; nsEventStatus status = nsEventStatus_eIgnore; switch (mEventMessage) { case NS_COMPOSITION_START: { @@ -444,10 +497,13 @@ mIsSynthesizedEvent); break; } - case NS_COMPOSITION_END: - case NS_COMPOSITION_CHANGE: { + case NS_COMPOSITION_CHANGE: + case NS_COMPOSITION_COMMIT_AS_IS: + case NS_COMPOSITION_COMMIT: { WidgetCompositionEvent compEvent(true, mEventMessage, widget); - compEvent.mData = mData; + if (mEventMessage != NS_COMPOSITION_COMMIT_AS_IS) { + compEvent.mData = mData; + } compEvent.mFlags.mIsSynthesizedForTests = mTextComposition->IsSynthesizedForTests(); IMEStateManager::DispatchCompositionEvent(mEventTarget, presContext, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/TextComposition.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/TextComposition.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/TextComposition.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/TextComposition.h 2014-11-26 21:45:58.000000000 +0000 @@ -250,6 +250,14 @@ void EditorDidHandleCompositionChangeEvent(); /** + * IsValidStateForComposition() returns true if it's safe to dispatch an event + * to the DOM tree. Otherwise, false. + * WARNING: This doesn't check script blocker state. It should be checked + * before dispatching the first event. + */ + bool IsValidStateForComposition(nsIWidget* aWidget) const; + + /** * DispatchCompositionEvent() dispatches the aCompositionEvent to the mContent * synchronously. The caller must ensure that it's safe to dispatch the event. */ @@ -268,6 +276,18 @@ const WidgetCompositionEvent* aCompositionEvent); /** + * CloneAndDispatchAs() dispatches a composition event which is + * duplicateed from aCompositionEvent and set the aMessage. + * + * @return Returns BaseEventFlags which is the result of dispatched event. + */ + BaseEventFlags CloneAndDispatchAs( + const WidgetCompositionEvent* aCompositionEvent, + uint32_t aMessage, + nsEventStatus* aStatus = nullptr, + EventDispatchingCallback* aCallBack = nullptr); + + /** * If IME has already dispatched compositionend event but it was discarded * by PresShell due to not safe to dispatch, this returns true. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/UIEvent.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/UIEvent.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/events/UIEvent.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/events/UIEvent.h 2014-11-26 21:45:58.000000000 +0000 @@ -60,7 +60,7 @@ LayoutDeviceIntPoint offset = aEvent->refPoint + LayoutDeviceIntPoint::FromUntyped(event->widget->WidgetToScreenOffset()); nscoord factor = - aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel(); + aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor), nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor)); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Fetch.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Fetch.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Fetch.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Fetch.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -112,7 +112,7 @@ }; already_AddRefed -FetchRequest(nsIGlobalObject* aGlobal, const RequestOrScalarValueString& aInput, +FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, const RequestInit& aInit, ErrorResult& aRv) { nsRefPtr p = Promise::Create(aGlobal, aRv); @@ -316,7 +316,7 @@ } nsresult -ExtractFromScalarValueString(const nsString& aStr, +ExtractFromUSVString(const nsString& aStr, nsIInputStream** aStream, nsCString& aContentType) { @@ -365,7 +365,7 @@ } nsresult -ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit, +ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams& aBodyInit, nsIInputStream** aStream, nsCString& aContentType) { @@ -380,10 +380,10 @@ } else if (aBodyInit.IsBlob()) { const File& blob = aBodyInit.GetAsBlob(); return ExtractFromBlob(blob, aStream, aContentType); - } else if (aBodyInit.IsScalarValueString()) { + } else if (aBodyInit.IsUSVString()) { nsAutoString str; - str.Assign(aBodyInit.GetAsScalarValueString()); - return ExtractFromScalarValueString(str, aStream, aContentType); + str.Assign(aBodyInit.GetAsUSVString()); + return ExtractFromUSVString(str, aStream, aContentType); } else if (aBodyInit.IsURLSearchParams()) { URLSearchParams& params = aBodyInit.GetAsURLSearchParams(); return ExtractFromURLSearchParams(params, aStream, aContentType); @@ -394,7 +394,7 @@ } nsresult -ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit, +ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams& aBodyInit, nsIInputStream** aStream, nsCString& aContentType) { @@ -409,10 +409,10 @@ } else if (aBodyInit.IsBlob()) { const File& blob = aBodyInit.GetAsBlob(); return ExtractFromBlob(blob, aStream, aContentType); - } else if (aBodyInit.IsScalarValueString()) { + } else if (aBodyInit.IsUSVString()) { nsAutoString str; - str.Assign(aBodyInit.GetAsScalarValueString()); - return ExtractFromScalarValueString(str, aStream, aContentType); + str.Assign(aBodyInit.GetAsUSVString()); + return ExtractFromUSVString(str, aStream, aContentType); } else if (aBodyInit.IsURLSearchParams()) { URLSearchParams& params = aBodyInit.GetAsURLSearchParams(); return ExtractFromURLSearchParams(params, aStream, aContentType); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Fetch.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Fetch.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Fetch.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Fetch.h 2014-11-26 21:45:58.000000000 +0000 @@ -18,18 +18,18 @@ namespace mozilla { namespace dom { -class ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams; +class ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams; class InternalRequest; -class OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams; +class OwningArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams; class Promise; -class RequestOrScalarValueString; +class RequestOrUSVString; namespace workers { class WorkerPrivate; } // namespace workers already_AddRefed -FetchRequest(nsIGlobalObject* aGlobal, const RequestOrScalarValueString& aInput, +FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, const RequestInit& aInit, ErrorResult& aRv); nsresult @@ -41,7 +41,7 @@ * Stores content type in out param aContentType. */ nsresult -ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit, +ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams& aBodyInit, nsIInputStream** aStream, nsCString& aContentType); @@ -49,7 +49,7 @@ * Non-owning version. */ nsresult -ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit, +ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams& aBodyInit, nsIInputStream** aStream, nsCString& aContentType); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Request.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Request.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Request.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Request.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -49,7 +49,7 @@ /*static*/ already_AddRefed Request::Constructor(const GlobalObject& aGlobal, - const RequestOrScalarValueString& aInput, + const RequestOrUSVString& aInput, const RequestInit& aInit, ErrorResult& aRv) { nsRefPtr request; @@ -76,9 +76,9 @@ RequestMode fallbackMode = RequestMode::EndGuard_; RequestCredentials fallbackCredentials = RequestCredentials::EndGuard_; - if (aInput.IsScalarValueString()) { + if (aInput.IsUSVString()) { nsString input; - input.Assign(aInput.GetAsScalarValueString()); + input.Assign(aInput.GetAsUSVString()); nsString requestURL; if (NS_IsMainThread()) { @@ -191,7 +191,7 @@ } if (aInit.mBody.WasPassed()) { - const OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& bodyInit = aInit.mBody.Value(); + const OwningArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams& bodyInit = aInit.mBody.Value(); nsCOMPtr stream; nsCString contentType; aRv = ExtractByteStreamFromBody(bodyInit, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Request.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Request.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Request.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Request.h 2014-11-26 21:45:58.000000000 +0000 @@ -23,7 +23,7 @@ class Headers; class InternalHeaders; class Promise; -class RequestOrScalarValueString; +class RequestOrUSVString; class Request MOZ_FINAL : public nsISupports , public nsWrapperCache @@ -89,7 +89,7 @@ GetBody(nsIInputStream** aStream) { return mRequest->GetBody(aStream); } static already_AddRefed - Constructor(const GlobalObject& aGlobal, const RequestOrScalarValueString& aInput, + Constructor(const GlobalObject& aGlobal, const RequestOrUSVString& aInput, const RequestInit& aInit, ErrorResult& rv); nsIGlobalObject* GetParentObject() const diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Response.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Response.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Response.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Response.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -56,14 +56,14 @@ { ErrorResult result; ResponseInit init; - Optional body; + Optional body; nsRefPtr r = Response::Constructor(aGlobal, body, init, result); return r.forget(); } /*static*/ already_AddRefed Response::Constructor(const GlobalObject& aGlobal, - const Optional& aBody, + const Optional& aBody, const ResponseInit& aInit, ErrorResult& aRv) { if (aInit.mStatus < 200 || aInit.mStatus > 599) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Response.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Response.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fetch/Response.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fetch/Response.h 2014-11-26 21:45:58.000000000 +0000 @@ -19,7 +19,7 @@ namespace mozilla { namespace dom { -class ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams; +class ArrayBufferOrArrayBufferViewOrUSVStringOrURLSearchParams; class Headers; class InternalHeaders; class Promise; @@ -87,7 +87,7 @@ static already_AddRefed Constructor(const GlobalObject& aGlobal, - const Optional& aBody, + const Optional& aBody, const ResponseInit& aInit, ErrorResult& rv); nsIGlobalObject* GetParentObject() const diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fmradio/FMRadioService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fmradio/FMRadioService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/fmradio/FMRadioService.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/fmradio/FMRadioService.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -10,6 +10,7 @@ #include "nsIAudioManager.h" #include "AudioManager.h" #include "nsDOMClassInfo.h" +#include "mozilla/LazyIdleThread.h" #include "mozilla/Preferences.h" #include "mozilla/dom/FMRadioChild.h" #include "mozilla/dom/ScriptSettings.h" @@ -19,6 +20,8 @@ #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/SettingChangeNotificationBinding.h" +#define TUNE_THREAD_TIMEOUT_MS 5000 + #define BAND_87500_108000_kHz 1 #define BAND_76000_108000_kHz 2 #define BAND_76000_90000_kHz 3 @@ -161,9 +164,10 @@ FMRadioService* fmRadioService = FMRadioService::Singleton(); if (!fmRadioService->mTuneThread) { - // SeekRunnable and SetFrequencyRunnable run on this thread. - // These call ioctls that can stall the main thread, so we run them here. - NS_NewNamedThread("FM Tuning", getter_AddRefs(fmRadioService->mTuneThread)); + // SeekRunnable and SetFrequencyRunnable run on this thread. These + // call ioctls that can stall the main thread, so we run them here. + fmRadioService->mTuneThread = new LazyIdleThread( + TUNE_THREAD_TIMEOUT_MS, NS_LITERAL_CSTRING("FM Tuning")); } return NS_OK; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLCanvasElement.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLCanvasElement.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLCanvasElement.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLCanvasElement.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -34,6 +34,7 @@ #include "nsNetUtil.h" #include "nsStreamUtils.h" #include "ActiveLayerTracker.h" +#include "WebGL1Context.h" #include "WebGL2Context.h" using namespace mozilla::layers; @@ -648,71 +649,71 @@ return NS_OK; } -nsresult -HTMLCanvasElement::GetContextHelper(const nsAString& aContextId, - nsICanvasRenderingContextInternal **aContext) +static bool +GetCanvasContextType(const nsAString& str, CanvasContextType* const out_type) { - NS_ENSURE_ARG(aContext); - - if (aContextId.EqualsLiteral("2d")) { - Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1); - nsRefPtr ctx = - new CanvasRenderingContext2D(); + if (str.EqualsLiteral("2d")) { + *out_type = CanvasContextType::Canvas2D; + return true; + } - ctx->SetCanvasElement(this); - ctx.forget(aContext); - return NS_OK; + if (str.EqualsLiteral("experimental-webgl")) { + *out_type = CanvasContextType::WebGL1; + return true; } - if (WebGL2Context::IsSupported() && - aContextId.EqualsLiteral("experimental-webgl2")) - { - Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); - nsRefPtr ctx = WebGL2Context::Create(); +#ifdef MOZ_WEBGL_CONFORMANT + if (str.EqualsLiteral("webgl")) { + /* WebGL 1.0, $2.1 "Context Creation": + * If the user agent supports both the webgl and experimental-webgl + * canvas context types, they shall be treated as aliases. + */ + *out_type = CanvasContextType::WebGL1; + return true; + } +#endif - if (ctx == nullptr) { - return NS_ERROR_NOT_IMPLEMENTED; + if (WebGL2Context::IsSupported()) { + if (str.EqualsLiteral("experimental-webgl2")) { + *out_type = CanvasContextType::WebGL2; + return true; } - - ctx->SetCanvasElement(this); - ctx.forget(aContext); - return NS_OK; } - NS_ConvertUTF16toUTF8 ctxId(aContextId); + return false; +} - // check that ctxId is clamped to A-Za-z0-9_- - for (uint32_t i = 0; i < ctxId.Length(); i++) { - if ((ctxId[i] < 'A' || ctxId[i] > 'Z') && - (ctxId[i] < 'a' || ctxId[i] > 'z') && - (ctxId[i] < '0' || ctxId[i] > '9') && - (ctxId[i] != '-') && - (ctxId[i] != '_')) - { - // XXX ERRMSG we need to report an error to developers here! (bug 329026) - return NS_OK; - } - } +static already_AddRefed +CreateContextForCanvas(CanvasContextType contextType, HTMLCanvasElement* canvas) +{ + nsRefPtr ret; + + switch (contextType) { + case CanvasContextType::Canvas2D: + Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1); + ret = new CanvasRenderingContext2D(); + break; - nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id="); - ctxString.Append(ctxId); + case CanvasContextType::WebGL1: + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); - nsresult rv; - nsCOMPtr ctx = - do_CreateInstance(ctxString.get(), &rv); - if (rv == NS_ERROR_OUT_OF_MEMORY) { - *aContext = nullptr; - return NS_ERROR_OUT_OF_MEMORY; - } - if (NS_FAILED(rv)) { - *aContext = nullptr; - // XXX ERRMSG we need to report an error to developers here! (bug 329026) - return NS_OK; + ret = WebGL1Context::Create(); + if (!ret) + return nullptr; + break; + + case CanvasContextType::WebGL2: + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); + + ret = WebGL2Context::Create(); + if (!ret) + return nullptr; + break; } + MOZ_ASSERT(ret); - ctx->SetCanvasElement(this); - ctx.forget(aContext); - return NS_OK; + ret->SetCanvasElement(canvas); + return ret.forget(); } nsresult @@ -720,65 +721,49 @@ nsISupports** aContext) { ErrorResult rv; - *aContext = - GetContext(nullptr, aContextId, JS::NullHandleValue, rv).take(); + *aContext = GetContext(nullptr, aContextId, JS::NullHandleValue, rv).take(); return rv.ErrorCode(); } -static bool -IsContextIdWebGL(const nsAString& str) -{ - return str.EqualsLiteral("webgl") || - str.EqualsLiteral("experimental-webgl"); -} - already_AddRefed HTMLCanvasElement::GetContext(JSContext* aCx, const nsAString& aContextId, JS::Handle aContextOptions, ErrorResult& rv) { - if (mCurrentContextId.IsEmpty()) { - rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext)); - if (rv.Failed() || !mCurrentContext) { + CanvasContextType contextType; + if (!GetCanvasContextType(aContextId, &contextType)) + return nullptr; + + if (!mCurrentContext) { + // This canvas doesn't have a context yet. + + nsRefPtr context; + context = CreateContextForCanvas(contextType, this); + if (!context) return nullptr; - } // Ensure that the context participates in CC. Note that returning a // CC participant from QI doesn't addref. - nsXPCOMCycleCollectionParticipant *cp = nullptr; - CallQueryInterface(mCurrentContext, &cp); + nsXPCOMCycleCollectionParticipant* cp = nullptr; + CallQueryInterface(context, &cp); if (!cp) { - mCurrentContext = nullptr; rv.Throw(NS_ERROR_FAILURE); return nullptr; } + mCurrentContext = context.forget(); + mCurrentContextType = contextType; + rv = UpdateContext(aCx, aContextOptions); if (rv.Failed()) { rv = NS_OK; // See bug 645792 return nullptr; } - mCurrentContextId.Assign(aContextId); - } - - if (!mCurrentContextId.Equals(aContextId)) { - if (IsContextIdWebGL(aContextId) && - IsContextIdWebGL(mCurrentContextId)) - { - // Warn when we get a request for a webgl context with an id that differs - // from the id it was created with. - nsCString creationId = NS_LossyConvertUTF16toASCII(mCurrentContextId); - nsCString requestId = NS_LossyConvertUTF16toASCII(aContextId); - JS_ReportWarning(aCx, "WebGL: Retrieving a WebGL context from a canvas " - "via a request id ('%s') different from the id used " - "to create the context ('%s') is not allowed.", - requestId.get(), - creationId.get()); - } - - //XXX eventually allow for more than one active context on a given canvas - return nullptr; + } else { + // We already have a context of some type. + if (contextType != mCurrentContextType) + return nullptr; } nsCOMPtr context = mCurrentContext; @@ -798,22 +783,28 @@ if (!aContextId.EqualsLiteral("2d")) return NS_ERROR_INVALID_ARG; - if (mCurrentContextId.IsEmpty()) { - nsresult rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext)); - NS_ENSURE_SUCCESS(rv, rv); - if (!mCurrentContext) { + CanvasContextType contextType = CanvasContextType::Canvas2D; + + if (!mCurrentContext) { + // This canvas doesn't have a context yet. + + nsRefPtr context; + context = CreateContextForCanvas(contextType, this); + if (!context) { + *aContext = nullptr; return NS_OK; } + mCurrentContext = context; mCurrentContext->SetIsIPC(true); + mCurrentContextType = contextType; - rv = UpdateContext(nullptr, JS::NullHandleValue); + nsresult rv = UpdateContext(nullptr, JS::NullHandleValue); NS_ENSURE_SUCCESS(rv, rv); - - mCurrentContextId.Assign(aContextId); - } else if (!mCurrentContextId.Equals(aContextId)) { - //XXX eventually allow for more than one active context on a given canvas - return NS_ERROR_INVALID_ARG; + } else { + // We already have a context of some type. + if (contextType != mCurrentContextType) + return NS_ERROR_INVALID_ARG; } NS_ADDREF (*aContext = mCurrentContext); @@ -831,21 +822,18 @@ nsresult rv = mCurrentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque)); if (NS_FAILED(rv)) { mCurrentContext = nullptr; - mCurrentContextId.Truncate(); return rv; } rv = mCurrentContext->SetContextOptions(aCx, aNewContextOptions); if (NS_FAILED(rv)) { mCurrentContext = nullptr; - mCurrentContextId.Truncate(); return rv; } rv = mCurrentContext->SetDimensions(sz.width, sz.height); if (NS_FAILED(rv)) { mCurrentContext = nullptr; - mCurrentContextId.Truncate(); return rv; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLCanvasElement.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLCanvasElement.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLCanvasElement.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLCanvasElement.h 2014-11-26 21:45:58.000000000 +0000 @@ -7,6 +7,7 @@ #define mozilla_dom_HTMLCanvasElement_h #include "mozilla/Attributes.h" +#include "mozilla/TypedEnum.h" #include "nsIDOMHTMLCanvasElement.h" #include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" @@ -35,6 +36,12 @@ class HTMLCanvasPrintState; class PrintCallback; +MOZ_BEGIN_ENUM_CLASS(CanvasContextType, uint8_t) + Canvas2D, + WebGL1, + WebGL2 +MOZ_END_ENUM_CLASS(CanvasContextType) + class HTMLCanvasElement MOZ_FINAL : public nsGenericHTMLElement, public nsIDOMHTMLCanvasElement { @@ -229,11 +236,9 @@ nsresult MozGetAsFileImpl(const nsAString& aName, const nsAString& aType, nsIDOMFile** aResult); - nsresult GetContextHelper(const nsAString& aContextId, - nsICanvasRenderingContextInternal **aContext); void CallPrintCallback(); - nsString mCurrentContextId; + CanvasContextType mCurrentContextType; nsRefPtr mOriginalCanvas; nsRefPtr mPrintCallback; nsCOMPtr mCurrentContext; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLFormElement.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLFormElement.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLFormElement.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLFormElement.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -61,6 +61,8 @@ #include "nsIDOMHTMLButtonElement.h" #include "nsSandboxFlags.h" +#include "nsIContentSecurityPolicy.h" + // images #include "mozilla/dom/HTMLImageElement.h" @@ -1625,6 +1627,19 @@ nsIScriptSecurityManager::STANDARD); NS_ENSURE_SUCCESS(rv, rv); + // Check if CSP allows this form-action + nsCOMPtr csp; + rv = NodePrincipal()->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, rv); + if (csp) { + bool permitsFormAction = true; + rv = csp->PermitsFormAction(actionURL, &permitsFormAction); + NS_ENSURE_SUCCESS(rv, rv); + if (!permitsFormAction) { + rv = NS_ERROR_CSP_FORM_ACTION_VIOLATION; + } + } + // // Assign to the output // diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLInputElement.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLInputElement.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLInputElement.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLInputElement.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -1032,11 +1032,12 @@ nsCOMPtr prefCallback = new UploadLastDir::ContentPrefCallback(aFilePicker, aFpCallback); +#ifdef MOZ_B2G if (XRE_GetProcessType() == GeckoProcessType_Content) { - // FIXME (bug 949666): Run this code in the parent process. prefCallback->HandleCompletion(nsIContentPrefCallback2::COMPLETE_ERROR); return NS_OK; } +#endif // Attempt to get the CPS, if it's not present we'll fallback to use the Desktop folder nsCOMPtr contentPrefService = @@ -1062,10 +1063,11 @@ return NS_OK; } +#ifdef MOZ_B2G if (XRE_GetProcessType() == GeckoProcessType_Content) { - // FIXME (bug 949666): Run this code in the parent process. return NS_OK; } +#endif nsCOMPtr docURI = aDoc->GetDocumentURI(); NS_PRECONDITION(docURI, "docURI is null"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLMediaElement.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLMediaElement.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLMediaElement.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLMediaElement.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -3719,7 +3719,8 @@ EmptyCString(), false); // Set the Referer header - aChannel->SetReferrer(OwnerDoc()->GetDocumentURI()); + aChannel->SetReferrerWithPolicy(OwnerDoc()->GetDocumentURI(), + OwnerDoc()->GetReferrerPolicy()); } void HTMLMediaElement::FireTimeUpdate(bool aPeriodic) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLMetaElement.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLMetaElement.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/HTMLMetaElement.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/HTMLMetaElement.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -77,7 +77,21 @@ nsAutoString content; rv = GetContent(content); NS_ENSURE_SUCCESS(rv, rv); - nsContentUtils::ProcessViewportInfo(aDocument, content); + nsContentUtils::ProcessViewportInfo(aDocument, content); + } + if (aDocument && + AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::referrer, eIgnoreCase)) { + nsAutoString content; + rv = GetContent(content); + NS_ENSURE_SUCCESS(rv, rv); + + // Referrer Policy spec requires a element. + Element* headElt = aDocument->GetHeadElement(); + if (headElt && nsContentUtils::ContentIsDescendantOf(this, headElt)) { + content = nsContentUtils::TrimWhitespace(content); + aDocument->SetHeaderData(nsGkAtoms::referrer, content); + } } CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMMetaAdded")); return rv; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/ImageDocument.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/ImageDocument.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/ImageDocument.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/ImageDocument.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -459,20 +459,14 @@ if (aType == imgINotificationObserver::SIZE_AVAILABLE) { nsCOMPtr image; aRequest->GetImage(getter_AddRefs(image)); - return OnStartContainer(aRequest, image); + return OnSizeAvailable(aRequest, image); } - // Do these two off a script runner because decode complete notifications often - // come during painting and these will trigger invalidation. - if (aType == imgINotificationObserver::DECODE_COMPLETE) { + // Run this using a script runner because HAS_TRANSPARENCY notifications can + // come during painting and this will trigger invalidation. + if (aType == imgINotificationObserver::HAS_TRANSPARENCY) { nsCOMPtr runnable = - NS_NewRunnableMethod(this, &ImageDocument::AddDecodedClass); - nsContentUtils::AddScriptRunner(runnable); - } - - if (aType == imgINotificationObserver::DISCARD) { - nsCOMPtr runnable = - NS_NewRunnableMethod(this, &ImageDocument::RemoveDecodedClass); + NS_NewRunnableMethod(this, &ImageDocument::OnHasTransparency); nsContentUtils::AddScriptRunner(runnable); } @@ -481,29 +475,14 @@ aRequest->GetImageStatus(&reqStatus); nsresult status = reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; - return OnStopRequest(aRequest, status); + return OnLoadComplete(aRequest, status); } return NS_OK; } void -ImageDocument::AddDecodedClass() -{ - if (!mImageContent || nsContentUtils::IsChildOfSameType(this)) { - return; - } - - nsDOMTokenList* classList = mImageContent->AsElement()->ClassList(); - mozilla::ErrorResult rv; - // Update the background-color of the image only after the - // image has been decoded to prevent flashes of just the - // background-color. - classList->Add(NS_LITERAL_STRING("decoded"), rv); -} - -void -ImageDocument::RemoveDecodedClass() +ImageDocument::OnHasTransparency() { if (!mImageContent || nsContentUtils::IsChildOfSameType(this)) { return; @@ -511,8 +490,7 @@ nsDOMTokenList* classList = mImageContent->AsElement()->ClassList(); mozilla::ErrorResult rv; - // Remove any decoded-related styling when the image is unloaded. - classList->Remove(NS_LITERAL_STRING("decoded"), rv); + classList->Add(NS_LITERAL_STRING("transparent"), rv); } void @@ -535,7 +513,7 @@ } nsresult -ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage) +ImageDocument::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage) { // Styles have not yet been applied, so we don't know the final size. For now, // default to the image's intrinsic size. @@ -551,8 +529,7 @@ } nsresult -ImageDocument::OnStopRequest(imgIRequest *aRequest, - nsresult aStatus) +ImageDocument::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus) { UpdateTitleAndCharset(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/ImageDocument.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/ImageDocument.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/ImageDocument.h 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/ImageDocument.h 2014-11-26 21:45:58.000000000 +0000 @@ -51,9 +51,6 @@ void DefaultCheckOverflowing() { CheckOverflowing(mResizeImageByDefault); } - void AddDecodedClass(); - void RemoveDecodedClass(); - // WebIDL API virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE; @@ -107,8 +104,9 @@ }; void SetModeClass(eModeClasses mode); - nsresult OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage); - nsresult OnStopRequest(imgIRequest *aRequest, nsresult aStatus); + nsresult OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage); + nsresult OnLoadComplete(imgIRequest* aRequest, nsresult aStatus); + void OnHasTransparency(); nsCOMPtr mImageContent; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/nsTextEditorState.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/nsTextEditorState.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/nsTextEditorState.cpp 2014-11-14 09:37:23.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/nsTextEditorState.cpp 2014-11-26 21:45:58.000000000 +0000 @@ -227,6 +227,7 @@ NS_IMETHOD GetCaretEnabled(bool *_retval); NS_IMETHOD GetCaretVisible(bool *_retval); NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility); + NS_IMETHOD PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend) MOZ_OVERRIDE; NS_IMETHOD CharacterMove(bool aForward, bool aExtend); NS_IMETHOD CharacterExtendForDelete(); NS_IMETHOD CharacterExtendForBackspace(); @@ -446,6 +447,15 @@ } NS_IMETHODIMP +nsTextInputSelectionImpl::PhysicalMove(int16_t aDirection, int16_t aAmount, + bool aExtend) +{ + if (mFrameSelection) + return mFrameSelection->PhysicalMove(aDirection, aAmount, aExtend); + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP nsTextInputSelectionImpl::CharacterMove(bool aForward, bool aExtend) { if (mFrameSelection) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/test/forms/test_input_color_picker_popup.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/test/forms/test_input_color_picker_popup.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/html/test/forms/test_input_color_picker_popup.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/html/test/forms/test_input_color_picker_popup.html 2014-11-26 21:45:58.000000000 +0000 @@ -9,6 +9,7 @@ + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/test_table_rollback.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/test_table_rollback.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/test_table_rollback.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/test_table_rollback.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,19 @@ + + + + Indexed Database Test + + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/unit/test_table_locks.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/unit/test_table_locks.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/unit/test_table_locks.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/unit/test_table_locks.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,116 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const dbName = ("window" in this) ? window.location.pathname : "test"; +const dbVersion = 1; +const objName1 = "o1"; +const objName2 = "o2"; +const idxName1 = "i1"; +const idxName2 = "i2"; +const idxKeyPathProp = "idx"; +const objDataProp = "data"; +const objData = "1234567890"; +const objDataCount = 5; +const loopCount = 100; + +let testGenerator = testSteps(); + +function testSteps() +{ + let req = indexedDB.open(dbName, dbVersion); + req.onerror = errorHandler; + req.onupgradeneeded = grabEventAndContinueHandler; + req.onsuccess = grabEventAndContinueHandler; + + let event = yield undefined; + + is(event.type, "upgradeneeded", "Got upgradeneeded event"); + + let db = event.target.result; + + let objectStore1 = db.createObjectStore(objName1); + objectStore1.createIndex(idxName1, idxKeyPathProp); + + let objectStore2 = db.createObjectStore(objName2); + objectStore2.createIndex(idxName2, idxKeyPathProp); + + for (let i = 0; i < objDataCount; i++) { + var data = { }; + data[objDataProp] = objData; + data[idxKeyPathProp] = objDataCount - i - 1; + + objectStore1.add(data, i); + objectStore2.add(data, i); + } + + event = yield undefined; + + is(event.type, "success", "Got success event"); + + doReadOnlyTransaction(db, 0, loopCount); + doReadWriteTransaction(db, 0, loopCount); + + // Wait for readonly and readwrite transaction loops to complete. + yield undefined; + yield undefined; + + finishTest(); + yield undefined; +} + +function doReadOnlyTransaction(db, key, remaining) +{ + if (!remaining) { + info("Finished all readonly transactions"); + continueToNextStep(); + return; + } + + info("Starting readonly transaction for key " + key + ", " + remaining + + " loops left"); + + let objectStore = db.transaction(objName1, "readonly").objectStore(objName1); + let index = objectStore.index(idxName1); + + index.openKeyCursor(key, "prev").onsuccess = function(event) { + let cursor = event.target.result; + ok(cursor, "Got readonly cursor"); + + objectStore.get(cursor.primaryKey).onsuccess = function(event) { + if (++key == objDataCount) { + key = 0; + } + doReadOnlyTransaction(db, key, remaining - 1); + } + }; +} + +function doReadWriteTransaction(db, key, remaining) +{ + if (!remaining) { + info("Finished all readwrite transactions"); + continueToNextStep(); + return; + } + + info("Starting readwrite transaction for key " + key + ", " + remaining + + " loops left"); + + let objectStore = db.transaction(objName2, "readwrite").objectStore(objName2); + objectStore.openCursor(key).onsuccess = function(event) { + let cursor = event.target.result; + ok(cursor, "Got readwrite cursor"); + + let value = cursor.value; + value[idxKeyPathProp]++; + + cursor.update(value).onsuccess = function(event) { + if (++key == objDataCount) { + key = 0; + } + doReadWriteTransaction(db, key, remaining - 1); + } + }; +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/unit/test_table_rollback.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/unit/test_table_rollback.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/unit/test_table_rollback.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/unit/test_table_rollback.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,115 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +let testGenerator = testSteps(); + +function testSteps() +{ + const dbName = ("window" in this) ? window.location.pathname : "test"; + const objName1 = "foo"; + const objName2 = "bar"; + const data1 = "1234567890"; + const data2 = "0987654321"; + const dataCount = 500; + + let request = indexedDB.open(dbName, 1); + request.onerror = errorHandler; + request.onupgradeneeded = grabEventAndContinueHandler; + + let event = yield undefined; + + is(event.type, "upgradeneeded", "Got upgradeneeded"); + + request.onupgradeneeded = errorHandler; + request.onsuccess = grabEventAndContinueHandler; + + let db = request.result; + + let objectStore1 = db.createObjectStore(objName1, { autoIncrement: true }); + let objectStore2 = db.createObjectStore(objName2, { autoIncrement: true }); + + info("Created object stores, adding data"); + + for (let i = 0; i < dataCount; i++) { + objectStore1.add(data1); + objectStore2.add(data2); + } + + info("Done adding data"); + + event = yield undefined; + + is(event.type, "success", "Got success"); + + let readResult = null; + let readError = null; + let writeAborted = false; + + info("Creating readwrite transaction"); + + objectStore1 = db.transaction(objName1, "readwrite").objectStore(objName1); + objectStore1.openCursor().onsuccess = grabEventAndContinueHandler; + + event = yield undefined; + + let cursor = event.target.result; + is(cursor.value, data1, "Got correct data for readwrite transaction"); + + info("Modifying object store on readwrite transaction"); + + cursor.update(data2); + cursor.continue(); + + event = yield undefined; + + info("Done modifying object store on readwrite transaction, creating " + + "readonly transaction"); + + objectStore2 = db.transaction(objName2, "readonly").objectStore(objName2); + request = objectStore2.getAll(); + request.onsuccess = function(event) { + readResult = event.target.result; + is(readResult.length, + dataCount, + "Got correct number of results on readonly transaction"); + for (let i = 0; i < readResult.length; i++) { + is(readResult[i], data2, "Got correct data for readonly transaction"); + } + if (writeAborted) { + continueToNextStep(); + } + }; + request.onerror = function(event) { + readResult = null; + readError = event.target.error; + + ok(false, "Got read error: " + readError.name); + event.preventDefault(); + + if (writeAborted) { + continueToNextStep(); + } + } + + cursor = event.target.result; + is(cursor.value, data1, "Got correct data for readwrite transaction"); + + info("Aborting readwrite transaction"); + + cursor.source.transaction.abort(); + writeAborted = true; + + if (!readError && !readResult) { + info("Waiting for readonly transaction to complete"); + yield undefined; + } + + ok(readResult, "Got result from readonly transaction"); + is(readError, null, "No read error"); + is(writeAborted, true, "Aborted readwrite transaction"); + + finishTest(); + yield undefined; +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/unit/xpcshell-shared.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/unit/xpcshell-shared.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/indexedDB/test/unit/xpcshell-shared.ini 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/indexedDB/test/unit/xpcshell-shared.ini 2014-11-26 21:46:00.000000000 +0000 @@ -64,6 +64,8 @@ [test_setVersion_events.js] [test_setVersion_exclusion.js] [test_success_events_after_abort.js] +[test_table_locks.js] +[test_table_rollback.js] [test_traffic_jam.js] [test_transaction_abort.js] [test_transaction_abort_hang.js] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/inputmethod/forms.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/inputmethod/forms.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/inputmethod/forms.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/inputmethod/forms.js 2014-11-26 21:46:00.000000000 +0000 @@ -1277,14 +1277,7 @@ if (!this._isStarted) { return; } - // Update the composing text. - let compositionString = domWindowUtils.createCompositionStringSynthesizer(); - compositionString.setString(text); - // Set the cursor position to |text.length| so that the text will be - // committed before the cursor position. - compositionString.setCaret(text.length, 0); - compositionString.dispatchEvent(); - domWindowUtils.sendCompositionEvent('compositionend', text, ''); + domWindowUtils.sendCompositionEvent('compositioncommit', text, ''); this._isStarted = false; }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/base/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/base/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/base/moz.build 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/base/moz.build 2014-11-26 21:46:00.000000000 +0000 @@ -17,7 +17,6 @@ 'nsIDOMClientRectList.idl', 'nsIDOMConstructor.idl', 'nsIDOMCrypto.idl', - 'nsIDOMGlobalObjectConstructor.idl', 'nsIDOMGlobalPropertyInitializer.idl', 'nsIDOMHistory.idl', 'nsIDOMJSWindow.idl', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "domstubs.idl" - -[scriptable, uuid(cb439c73-0129-4289-a349-c5216e6b912a)] -interface nsIDOMGlobalObjectConstructor : nsISupports -{ - /* - * JS use only - * - * The constructor() method will be called with any parameters passed - * to the object constructor. - * If the JS implementation returns a value, it will be ignored. - */ - void constructor(); -}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl 2014-11-26 21:46:00.000000000 +0000 @@ -51,7 +51,7 @@ interface nsIJSRAIIHelper; interface nsIContentPermissionRequest; -[scriptable, uuid(e293355b-ae7f-4ef7-9237-452bcf3e9e6b)] +[scriptable, uuid(9621eb05-b498-4e87-a012-95d817987624)] interface nsIDOMWindowUtils : nsISupports { /** @@ -188,8 +188,6 @@ in float aTopMargin, in float aRightMargin, in float aBottomMargin, - in uint32_t aAlignmentX, - in uint32_t aAlignmentY, in nsIDOMElement aElement, in uint32_t aPriority); @@ -1038,11 +1036,13 @@ * Cannot be accessed from unprivileged context (not content-accessible) * Will throw a DOM security error if called without chrome privileges. * - * @param aType The event type: "compositionstart", "compositionend" or - * "compositionupdate". + * @param aType The event type: "compositionstart", + * "compositioncommitasis", or "compositioncommit". * @param aData The data property value. Note that this isn't applied * for compositionstart event because its value is the - * selected text which is automatically computed. + * selected text which is automatically computed. And also + * this isn't applied for compositioncommitasis because + * the last data will be set automatically. * @param aLocale The locale property value. */ void sendCompositionEvent(in AString aType, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMAttr.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMAttr.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMAttr.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMAttr.idl 2014-11-26 21:46:00.000000000 +0000 @@ -14,7 +14,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[builtinclass, uuid(7d0582bd-09a7-430e-969b-054abbea19fe)] +[builtinclass, uuid(7db491e8-a3a3-4432-ad67-e6c33e24ac6d)] interface nsIDOMAttr : nsIDOMNode { readonly attribute DOMString name; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMCDATASection.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMCDATASection.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMCDATASection.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMCDATASection.idl 2014-11-26 21:46:00.000000000 +0000 @@ -15,7 +15,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[uuid(4ac42d40-69b7-4506-b730-c41ec74b74bd)] +[uuid(e14ef131-34cc-40c8-9c99-a403c001184a)] interface nsIDOMCDATASection : nsIDOMText { }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMCharacterData.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMCharacterData.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMCharacterData.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMCharacterData.idl 2014-11-26 21:46:00.000000000 +0000 @@ -13,7 +13,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[uuid(844b8e7e-6d37-4fa1-8196-86e3afdfa0ca)] +[uuid(4109a2d2-e7af-445d-bb72-c7c9b875f35e)] interface nsIDOMCharacterData : nsIDOMNode { attribute DOMString data; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMComment.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMComment.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMComment.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMComment.idl 2014-11-26 21:46:00.000000000 +0000 @@ -14,7 +14,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[uuid(c1a1d2ea-e106-4ee8-806d-2633468e8098)] +[uuid(e7866ff8-b7fc-494f-87c0-fb017d8a4d30)] interface nsIDOMComment : nsIDOMCharacterData { }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMDocumentFragment.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMDocumentFragment.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMDocumentFragment.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMDocumentFragment.idl 2014-11-26 21:46:00.000000000 +0000 @@ -14,7 +14,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[builtinclass, uuid(24b34c61-7326-42d4-87ec-5d3b5c0b1b26)] +[builtinclass, uuid(48eb8d72-95bb-402e-a8fc-f2b187abcbdb)] interface nsIDOMDocumentFragment : nsIDOMNode { /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMDocument.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMDocument.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMDocument.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMDocument.idl 2014-11-26 21:46:00.000000000 +0000 @@ -32,7 +32,7 @@ * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html */ -[uuid(08c6400b-0b6d-4ce6-b88d-e7a15a9c7c03)] +[uuid(35dc5030-dc83-4291-88a2-0906c549788e)] interface nsIDOMDocument : nsIDOMNode { readonly attribute nsIDOMDocumentType doctype; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMDocumentType.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMDocumentType.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMDocumentType.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMDocumentType.idl 2014-11-26 21:46:00.000000000 +0000 @@ -15,7 +15,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[uuid(23c1f549-d40b-49b8-992e-2a1136afa13f)] +[uuid(cd7467b9-0f26-4787-a359-66e80ba8db92)] interface nsIDOMDocumentType : nsIDOMNode { readonly attribute DOMString name; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMElement.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMElement.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMElement.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMElement.idl 2014-11-26 21:46:00.000000000 +0000 @@ -15,7 +15,7 @@ * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-element */ -[uuid(59eb63f9-c8c0-41d2-bf73-739de43b17f9)] +[uuid(6289999b-1008-4269-b42a-413ec5a9d3f4)] interface nsIDOMElement : nsIDOMNode { readonly attribute DOMString tagName; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMNode.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMNode.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMNode.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMNode.idl 2014-11-26 21:46:00.000000000 +0000 @@ -16,7 +16,7 @@ * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html */ -[uuid(238222a9-7aa5-4804-9f86-484853ce4b15)] +[uuid(cc35b412-009b-46a3-9be0-76448f12548d)] interface nsIDOMNode : nsISupports { const unsigned short ELEMENT_NODE = 1; @@ -69,6 +69,9 @@ // Introduced in DOM Level 2: readonly attribute DOMString localName; + // For vtable compatibility (see bug 1078674) + [noscript] bool unusedPlaceholder(); + // Introduced in DOM Level 3: // This uses a binaryname to avoid warnings due to name collision with // nsINode::GetBaseURI diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMProcessingInstruction.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMProcessingInstruction.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMProcessingInstruction.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMProcessingInstruction.idl 2014-11-26 21:46:00.000000000 +0000 @@ -15,7 +15,7 @@ * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html */ -[uuid(d0163f44-8f5b-4234-b3aa-43cab64e2039)] +[uuid(5a139df7-04d0-438d-bd18-d8122564258f)] interface nsIDOMProcessingInstruction : nsIDOMCharacterData { readonly attribute DOMString target; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMText.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMText.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMText.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMText.idl 2014-11-26 21:46:00.000000000 +0000 @@ -13,7 +13,7 @@ * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html */ -[uuid(775bbd26-1581-4e54-b82c-5d9dc5a3363b)] +[uuid(67273994-6aff-4091-9de9-b788a249f783)] interface nsIDOMText : nsIDOMCharacterData { nsIDOMText splitText(in unsigned long offset) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMXMLDocument.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMXMLDocument.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/core/nsIDOMXMLDocument.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/core/nsIDOMXMLDocument.idl 2014-11-26 21:46:00.000000000 +0000 @@ -5,7 +5,7 @@ #include "nsIDOMDocument.idl" -[uuid(1d54e44a-2012-4567-805d-bd5455fc6421)] +[uuid(867379ce-165b-4b8c-8582-299b38096aa8)] interface nsIDOMXMLDocument : nsIDOMDocument { // DOM Level 3 Load & Save, DocumentLS diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/html/nsIDOMHTMLDocument.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/html/nsIDOMHTMLDocument.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/html/nsIDOMHTMLDocument.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/html/nsIDOMHTMLDocument.idl 2014-11-26 21:46:00.000000000 +0000 @@ -13,7 +13,7 @@ */ interface nsISelection; -[uuid(abf369fb-a8b2-4fba-95f5-9e4a896e40a8)] +[uuid(bd2a0a46-17e4-46ea-9e5d-6a97cf5e3b28)] interface nsIDOMHTMLDocument : nsIDOMDocument { attribute DOMString domain; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/html/nsIDOMHTMLElement.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/html/nsIDOMHTMLElement.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/html/nsIDOMHTMLElement.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/html/nsIDOMHTMLElement.idl 2014-11-26 21:46:00.000000000 +0000 @@ -19,7 +19,7 @@ * with changes from the work-in-progress WHATWG HTML specification: * http://www.whatwg.org/specs/web-apps/current-work/ */ -[uuid(8c9472c2-785a-40b6-ad47-4d98e64562bd)] +[uuid(b0c42392-d0e7-4f6a-beb5-a698ce648945)] interface nsIDOMHTMLElement : nsIDOMElement { // metadata attributes diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/security/nsIContentSecurityPolicy.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/security/nsIContentSecurityPolicy.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/security/nsIContentSecurityPolicy.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/security/nsIContentSecurityPolicy.idl 2014-11-26 21:46:00.000000000 +0000 @@ -207,6 +207,15 @@ boolean permitsBaseURI(in nsIURI aURI); /** + * Whether this policy allows submitting HTML forms to a given URI. + * + * @return + * Whether or not the provided URI is allowed to be used as a + * form's action URI. + */ + boolean permitsFormAction(in nsIURI aURI); + + /** * Delegate method called by the service when sub-elements of the protected * document are being loaded. Given a bit of information about the request, * decides whether or not the policy is satisfied. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/svg/nsIDOMSVGElement.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/svg/nsIDOMSVGElement.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/svg/nsIDOMSVGElement.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/svg/nsIDOMSVGElement.idl 2014-11-26 21:46:00.000000000 +0000 @@ -9,7 +9,7 @@ interface nsIDOMCSSValue; -[uuid(6618074e-0c77-4fec-8870-a6f79aa79b07)] +[uuid(c63517c5-8bab-4cd1-8694-bccafc32a195)] interface nsIDOMSVGElement : nsIDOMElement { // raises DOMException on setting diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/xul/nsIDOMXULDocument.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/xul/nsIDOMXULDocument.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/xul/nsIDOMXULDocument.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/xul/nsIDOMXULDocument.idl 2014-11-26 21:46:00.000000000 +0000 @@ -10,7 +10,7 @@ interface nsIObserver; interface nsIBoxObject; -[uuid(6f932360-ae43-4fa7-9200-66f64e05a356)] +[uuid(5d876ab0-5525-4f38-bc3b-f1190e3e3b90)] interface nsIDOMXULDocument : nsIDOMDocument { attribute nsIDOMNode popupNode; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/xul/nsIDOMXULElement.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/xul/nsIDOMXULElement.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/interfaces/xul/nsIDOMXULElement.idl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/interfaces/xul/nsIDOMXULElement.idl 2014-11-26 21:46:00.000000000 +0000 @@ -12,7 +12,7 @@ interface nsIBoxObject; -[uuid(ef62515d-3160-4463-abd7-fc9b7385ecef)] +[uuid(75435ab3-6863-42a1-ade3-025393d9e80e)] interface nsIDOMXULElement : nsIDOMElement { // Layout properties diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentChild.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentChild.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentChild.cpp 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentChild.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -16,6 +16,7 @@ #include "BlobChild.h" #include "CrashReporterChild.h" +#include "GeckoProfiler.h" #include "TabChild.h" #include "mozilla/Attributes.h" @@ -23,6 +24,7 @@ #include "mozilla/a11y/DocAccessibleChild.h" #endif #include "mozilla/Preferences.h" +#include "mozilla/docshell/OfflineCacheUpdateChild.h" #include "mozilla/dom/ContentBridgeChild.h" #include "mozilla/dom/ContentBridgeParent.h" #include "mozilla/dom/DOMStorageIPC.h" @@ -50,7 +52,10 @@ #define TARGET_SANDBOX_EXPORTS #include "mozilla/sandboxTarget.h" #include "nsDirectoryServiceDefs.h" -#elif defined(XP_LINUX) || defined(XP_MACOSX) +#elif defined(XP_LINUX) +#include "mozilla/Sandbox.h" +#include "mozilla/SandboxInfo.h" +#elif defined(XP_MACOSX) #include "mozilla/Sandbox.h" #endif #endif @@ -1130,10 +1135,10 @@ #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19 // For B2G >= KitKat, sandboxing is mandatory; this has already // been enforced by ContentParent::StartUp(). - MOZ_ASSERT(ContentProcessSandboxStatus() != kSandboxingWouldFail); + MOZ_ASSERT(SandboxInfo::Get().CanSandboxContent()); #else // Otherwise, sandboxing is best-effort. - if (ContentProcessSandboxStatus() == kSandboxingWouldFail) { + if (!SandboxInfo::Get().CanSandboxContent()) { return true; } #endif @@ -2258,6 +2263,25 @@ return true; } +POfflineCacheUpdateChild* +ContentChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI, + const URIParams& documentURI, + const bool& stickDocument, + const TabId& aTabId) +{ + NS_RUNTIMEABORT("unused"); + return nullptr; +} + +bool +ContentChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor) +{ + OfflineCacheUpdateChild* offlineCacheUpdate = + static_cast(actor); + NS_RELEASE(offlineCacheUpdate); + return true; +} + #ifdef MOZ_NUWA_PROCESS class CallNuwaSpawn : public nsRunnable { @@ -2364,6 +2388,48 @@ } return true; } + +bool +ContentChild::RecvStartProfiler(const uint32_t& aEntries, + const double& aInterval, + const nsTArray& aFeatures, + const nsTArray& aThreadNameFilters) +{ + nsTArray featureArray; + for (size_t i = 0; i < aFeatures.Length(); ++i) { + featureArray.AppendElement(aFeatures[i].get()); + } + + nsTArray threadNameFilterArray; + for (size_t i = 0; i < aThreadNameFilters.Length(); ++i) { + threadNameFilterArray.AppendElement(aThreadNameFilters[i].get()); + } + + profiler_start(aEntries, aInterval, featureArray.Elements(), featureArray.Length(), + threadNameFilterArray.Elements(), threadNameFilterArray.Length()); + + return true; +} + +bool +ContentChild::RecvStopProfiler() +{ + profiler_stop(); + return true; +} + +bool +ContentChild::AnswerGetProfile(nsCString* aProfile) +{ + char* profile = profiler_get_profile(); + if (profile) { + *aProfile = nsCString(profile, strlen(profile)); + free(profile); + } else { + *aProfile = EmptyCString(); + } + return true; +} PBrowserOrId ContentChild::GetBrowserOrId(TabChild* aTabChild) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentChild.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentChild.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentChild.h 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentChild.h 2014-11-26 21:46:00.000000000 +0000 @@ -358,6 +358,13 @@ virtual bool RecvOnAppThemeChanged() MOZ_OVERRIDE; + virtual bool RecvStartProfiler(const uint32_t& aEntries, + const double& aInterval, + const nsTArray& aFeatures, + const nsTArray& aThreadNameFilters) MOZ_OVERRIDE; + virtual bool RecvStopProfiler() MOZ_OVERRIDE; + virtual bool AnswerGetProfile(nsCString* aProfile) MOZ_OVERRIDE; + #ifdef ANDROID gfxIntSize GetScreenSize() { return mScreenSize; } #endif @@ -404,6 +411,14 @@ PBrowserOrId GetBrowserOrId(TabChild* aTabChild); + virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdateChild( + const URIParams& manifestURI, + const URIParams& documentURI, + const bool& stickDocument, + const TabId& aTabId) MOZ_OVERRIDE; + virtual bool + DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate) MOZ_OVERRIDE; + private: virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentParent.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentParent.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentParent.cpp 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentParent.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -35,6 +35,7 @@ #include "nsAccessibilityService.h" #endif #include "mozilla/ClearOnShutdown.h" +#include "mozilla/docshell/OfflineCacheUpdateParent.h" #include "mozilla/dom/DataStoreService.h" #include "mozilla/dom/DOMStorageIPC.h" #include "mozilla/dom/Element.h" @@ -84,6 +85,7 @@ #include "nsChromeRegistryChrome.h" #include "nsConsoleMessage.h" #include "nsConsoleService.h" +#include "nsContentUtils.h" #include "nsDebugImpl.h" #include "nsFrameMessageManager.h" #include "nsGeolocationSettings.h" @@ -192,13 +194,18 @@ #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX) -#include "mozilla/Sandbox.h" +#include "mozilla/SandboxInfo.h" #endif #ifdef MOZ_TOOLKIT_SEARCH #include "nsIBrowserSearchService.h" #endif +#ifdef MOZ_ENABLE_PROFILER_SPS +#include "nsIProfiler.h" +#include "nsIProfileSaveEvent.h" +#endif + static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static const char* sClipboardTextFlavors[] = { kUnicodeMime }; @@ -588,6 +595,11 @@ "a11y-init-or-shutdown", #endif "app-theme-changed", +#ifdef MOZ_ENABLE_PROFILER_SPS + "profiler-started", + "profiler-stopped", + "profiler-subprocess", +#endif }; /* static */ already_AddRefed @@ -687,7 +699,7 @@ #if defined(MOZ_CONTENT_SANDBOX) && defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19 // Require sandboxing on B2G >= KitKat. This condition must stay // in sync with ContentChild::RecvSetProcessSandbox. - if (ContentProcessSandboxStatus() == kSandboxingWouldFail) { + if (!SandboxInfo::Get().CanSandboxContent()) { // MOZ_CRASH strings are only for debug builds; make sure the // message is clear on non-debug builds as well: printf_stderr("Sandboxing support is required on this platform. " @@ -1022,6 +1034,7 @@ } nsRefPtr tp(new TabParent(constructorSender, tabId, aContext, chromeFlags)); + tp->SetInitedByParent(); tp->SetOwnerElement(aFrameElement); PBrowserParent* browser = constructorSender->SendPBrowserConstructor( @@ -1133,6 +1146,7 @@ uint32_t chromeFlags = 0; nsRefPtr tp = new TabParent(parent, tabId, aContext, chromeFlags); + tp->SetInitedByParent(); tp->SetOwnerElement(aFrameElement); PBrowserParent* browser = parent->SendPBrowserConstructor( // DeallocPBrowserParent() releases this ref. @@ -1487,6 +1501,14 @@ } } + const InfallibleTArray& ocuParents = + ManagedPOfflineCacheUpdateParent(); + for (uint32_t i = 0; i < ocuParents.Length(); ++i) { + nsRefPtr ocuParent = + static_cast(ocuParents[i]); + ocuParent->StopSendingMessagesToChild(); + } + // NB: must MarkAsDead() here so that this isn't accidentally // returned from Get*() while in the midst of shutdown. MarkAsDead(); @@ -1924,6 +1946,13 @@ // PID along with the warning. nsDebugImpl::SetMultiprocessMode("Parent"); +#if defined(XP_WIN) && !defined(MOZ_B2G) + // Request Windows message deferral behavior on our side of the PContent + // channel. Generally only applies to the situation where we get caught in + // a deadlock with the plugin process when sending CPOWs. + GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION); +#endif + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); ChildPrivileges privs = aIsNuwaProcess ? base::PRIVILEGES_INHERIT @@ -2776,6 +2805,31 @@ else if (!strcmp(aTopic, "app-theme-changed")) { unused << SendOnAppThemeChanged(); } +#ifdef MOZ_ENABLE_PROFILER_SPS + else if (!strcmp(aTopic, "profiler-started")) { + nsCOMPtr params(do_QueryInterface(aSubject)); + uint32_t entries; + double interval; + params->GetEntries(&entries); + params->GetInterval(&interval); + const nsTArray& features = params->GetFeatures(); + const nsTArray& threadFilterNames = params->GetThreadFilterNames(); + unused << SendStartProfiler(entries, interval, features, threadFilterNames); + } + else if (!strcmp(aTopic, "profiler-stopped")) { + unused << SendStopProfiler(); + } + else if (!strcmp(aTopic, "profiler-subprocess")) { + nsCOMPtr pse = do_QueryInterface(aSubject); + if (pse) { + nsCString result; + unused << CallGetProfile(&result); + if (!result.IsEmpty()) { + pse->AddSubProfile(result.get()); + } + } + } +#endif return NS_OK; } @@ -4317,6 +4371,62 @@ GetTabContextByContentProcess(this->ChildID())); } +mozilla::docshell::POfflineCacheUpdateParent* +ContentParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI, + const URIParams& aDocumentURI, + const bool& aStickDocument, + const TabId& aTabId) +{ + TabContext tabContext; + if (!ContentProcessManager::GetSingleton()-> + GetTabContextByProcessAndTabId(this->ChildID(), aTabId, &tabContext)) { + return nullptr; + } + nsRefPtr update = + new mozilla::docshell::OfflineCacheUpdateParent( + tabContext.OwnOrContainingAppId(), + tabContext.IsBrowserElement()); + // Use this reference as the IPDL reference. + return update.forget().take(); +} + +bool +ContentParent::RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor, + const URIParams& aManifestURI, + const URIParams& aDocumentURI, + const bool& aStickDocument, + const TabId& aTabId) +{ + MOZ_ASSERT(aActor); + + nsRefPtr update = + static_cast(aActor); + + nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aStickDocument); + if (NS_FAILED(rv) && IsAlive()) { + // Inform the child of failure. + unused << update->SendFinish(false, false); + } + + return true; +} + +bool +ContentParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor) +{ + // Reclaim the IPDL reference. + nsRefPtr update = + dont_AddRef(static_cast(aActor)); + return true; +} + +bool +ContentParent::RecvSetOfflinePermission(const Principal& aPrincipal) +{ + nsIPrincipal* principal = aPrincipal; + nsContentUtils::MaybeAllowOfflineAppByDefault(principal, nullptr); + return true; +} } // namespace dom } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentParent.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentParent.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentParent.h 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentParent.h 2014-11-26 21:46:00.000000000 +0000 @@ -311,6 +311,23 @@ virtual bool RecvDeallocateTabId(const TabId& aTabId) MOZ_OVERRIDE; nsTArray GetManagedTabContext(); + + virtual POfflineCacheUpdateParent* + AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI, + const URIParams& aDocumentURI, + const bool& aStickDocument, + const TabId& aTabId) MOZ_OVERRIDE; + virtual bool + RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor, + const URIParams& aManifestURI, + const URIParams& aDocumentURI, + const bool& stickDocument, + const TabId& aTabId) MOZ_OVERRIDE; + virtual bool + DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor) MOZ_OVERRIDE; + + virtual bool RecvSetOfflinePermission(const IPC::Principal& principal) MOZ_OVERRIDE; + protected: void OnChannelConnected(int32_t pid) MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentProcessManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentProcessManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentProcessManager.cpp 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentProcessManager.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -207,25 +207,29 @@ } } -nsTArray -ContentProcessManager::GetAppIdsByContentProcess(const ContentParentId& aChildCpId) +bool +ContentProcessManager::GetTabContextByProcessAndTabId(const ContentParentId& aChildCpId, + const TabId& aChildTabId, + /*out*/ TabContext* aTabContext) { MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aTabContext); - nsTArray appIdArray; auto iter = mContentParentMap.find(aChildCpId); if (NS_WARN_IF(iter == mContentParentMap.end())) { ASSERT_UNLESS_FUZZING(); - return Move(appIdArray); + return false; } - for (auto remoteFrameIter = iter->second.mRemoteFrames.begin(); - remoteFrameIter != iter->second.mRemoteFrames.end(); - ++remoteFrameIter) { - appIdArray.AppendElement(remoteFrameIter->second.mContext.OwnOrContainingAppId()); + auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId); + if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) { + ASSERT_UNLESS_FUZZING(); + return false; } - return Move(appIdArray); + *aTabContext = remoteFrameIter->second.mContext; + + return true; } nsTArray diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentProcessManager.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentProcessManager.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/ContentProcessManager.h 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/ContentProcessManager.h 2014-11-26 21:46:00.000000000 +0000 @@ -88,11 +88,12 @@ const TabId& aChildTabId); /** - * Get all app ids which are inside the given content process. - * XXX Currently not used. Plan to be used for bug 1020186. + * Get the TabContext by the given content process and tab id. */ - nsTArray - GetAppIdsByContentProcess(const ContentParentId& aChildCpId); + bool + GetTabContextByProcessAndTabId(const ContentParentId& aChildCpId, + const TabId& aChildTabId, + /*out*/ TabContext* aTabContext); /** * Get all TabContext which are inside the given content process. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/FilePickerParent.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/FilePickerParent.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/FilePickerParent.cpp 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/FilePickerParent.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -202,7 +202,8 @@ const nsString& aDefaultFile, const nsString& aDefaultExtension, const InfallibleTArray& aFilters, - const InfallibleTArray& aFilterNames) + const InfallibleTArray& aFilterNames, + const nsString& aDisplayDirectory) { if (!CreateFilePicker()) { unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel); @@ -219,6 +220,14 @@ mFilePicker->SetDefaultExtension(aDefaultExtension); mFilePicker->SetFilterIndex(aSelectedType); + if (!aDisplayDirectory.IsEmpty()) { + nsCOMPtr localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); + if (localFile) { + localFile->InitWithPath(aDisplayDirectory); + mFilePicker->SetDisplayDirectory(localFile); + } + } + mCallback = new FilePickerShownCallback(this); mFilePicker->Open(mCallback); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/FilePickerParent.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/FilePickerParent.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/FilePickerParent.h 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/FilePickerParent.h 2014-11-26 21:46:00.000000000 +0000 @@ -36,7 +36,8 @@ const nsString& aDefaultFile, const nsString& aDefaultExtension, const InfallibleTArray& aFilters, - const InfallibleTArray& aFilterNames) MOZ_OVERRIDE; + const InfallibleTArray& aFilterNames, + const nsString& aDisplayDirectory) MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/PBrowser.ipdl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/PBrowser.ipdl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/dom/ipc/PBrowser.ipdl 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/dom/ipc/PBrowser.ipdl 2014-11-26 21:46:00.000000000 +0000 @@ -14,7 +14,6 @@ include protocol PFilePicker; include protocol PIndexedDBPermissionRequest; include protocol PRenderFrame; -include protocol POfflineCacheUpdate; include protocol PPluginWidget; include DOMTypes; include JavaScriptTypes; @@ -80,13 +79,18 @@ manages PFilePicker; manages PIndexedDBPermissionRequest; manages PRenderFrame; - manages POfflineCacheUpdate; manages PPluginWidget; both: AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal); + /** + * Create a layout frame (encapsulating a remote layer tree) for + * the page that is currently loaded in the . + */ + PRenderFrame(); + parent: /* * Creates a new remoted nsIWidget connection for windowed plugins @@ -320,47 +324,6 @@ PIndexedDBPermissionRequest(Principal principal); /** - * Create a layout frame (encapsulating a remote layer tree) for - * the page that is currently loaded in the . - */ - sync PRenderFrame() - returns (ScrollingBehavior scrolling, - TextureFactoryIdentifier textureFactoryIdentifier, uint64_t layersId, - bool success); - - /** - * Starts an offline application cache update. - * @param manifestURI - * URI of the manifest to fetch, the application cache group ID - * @param documentURI - * URI of the document that referred the manifest - * @param stickDocument - * True if the update was initiated by a document load that referred - * a manifest. - * False if the update was initiated by applicationCache.update() call. - * - * Tells the update to carry the documentURI to a potential separate - * update of implicit (master) items. - * - * Why this argument? If the document was not found in an offline cache - * before load and refers a manifest and this manifest itself has not - * been changed since the last fetch, we will not do the application - * cache group update. But we must cache the document (identified by the - * documentURI). This argument will ensure that a previously uncached - * document will get cached and that we don't re-cache a document that - * has already been cached (stickDocument=false). - */ - POfflineCacheUpdate(URIParams manifestURI, URIParams documentURI, - bool stickDocument); - - /** - * Sets "offline-app" permission for the principal. Called when we hit - * a web app with the manifest attribute in and - * offline-apps.allow_by_default is set to true. - */ - SetOfflinePermission(Principal principal); - - /** * window.open from inside + + +Mozilla Bug 1094930 +

+ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/FilteringWrapper.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/FilteringWrapper.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/FilteringWrapper.cpp 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/FilteringWrapper.cpp 2014-11-26 21:46:04.000000000 +0000 @@ -102,36 +102,37 @@ template bool -FilteringWrapper::enumerate(JSContext *cx, HandleObject wrapper, - AutoIdVector &props) const +FilteringWrapper::getOwnEnumerablePropertyKeys(JSContext *cx, + HandleObject wrapper, + AutoIdVector &props) const { assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE); - return Base::enumerate(cx, wrapper, props) && + return Base::getOwnEnumerablePropertyKeys(cx, wrapper, props) && Filter(cx, wrapper, props); } template bool -FilteringWrapper::getOwnEnumerablePropertyKeys(JSContext *cx, - HandleObject wrapper, - AutoIdVector &props) const +FilteringWrapper::getEnumerablePropertyKeys(JSContext *cx, + HandleObject wrapper, + AutoIdVector &props) const { assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE); - return Base::getOwnEnumerablePropertyKeys(cx, wrapper, props) && + return Base::getEnumerablePropertyKeys(cx, wrapper, props) && Filter(cx, wrapper, props); } template bool FilteringWrapper::iterate(JSContext *cx, HandleObject wrapper, - unsigned flags, MutableHandleValue vp) const + unsigned flags, MutableHandleObject objp) const { assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE); // We refuse to trigger the iterator hook across chrome wrappers because // we don't know how to censor custom iterator objects. Instead we trigger // the default proxy iterate trap, which will ask enumerate() for the list // of (censored) ids. - return js::BaseProxyHandler::iterate(cx, wrapper, flags, vp); + return js::BaseProxyHandler::iterate(cx, wrapper, flags, objp); } template @@ -238,7 +239,7 @@ // All properties on cross-origin objects are supposed |own|, despite what // the underlying native object may report. Override the inherited trap to // avoid passing JSITER_OWNONLY as a flag. - return SecurityXrayDOM::enumerate(cx, wrapper, JSITER_HIDDEN, props); + return SecurityXrayDOM::getPropertyKeys(cx, wrapper, JSITER_HIDDEN, props); } bool @@ -259,8 +260,8 @@ } bool -CrossOriginXrayWrapper::enumerate(JSContext *cx, JS::Handle wrapper, - JS::AutoIdVector &props) const +CrossOriginXrayWrapper::getEnumerablePropertyKeys(JSContext *cx, JS::Handle wrapper, + JS::AutoIdVector &props) const { // Cross-origin properties are non-enumerable. return true; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/FilteringWrapper.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/FilteringWrapper.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/FilteringWrapper.h 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/FilteringWrapper.h 2014-11-26 21:46:04.000000000 +0000 @@ -33,16 +33,16 @@ JS::MutableHandle desc) const MOZ_OVERRIDE; virtual bool ownPropertyKeys(JSContext *cx, JS::Handle wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE; - virtual bool enumerate(JSContext *cx, JS::Handle wrapper, - JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle wrapper, JS::Handle id, JS::MutableHandle desc) const MOZ_OVERRIDE; virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE; + virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle wrapper, + JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, JS::Handle wrapper, unsigned flags, - JS::MutableHandle vp) const MOZ_OVERRIDE; + JS::MutableHandle objp) const MOZ_OVERRIDE; virtual bool call(JSContext *cx, JS::Handle wrapper, const JS::CallArgs &args) const MOZ_OVERRIDE; @@ -80,12 +80,12 @@ JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, JS::Handle wrapper, JS::Handle id, bool *bp) const MOZ_OVERRIDE; - virtual bool enumerate(JSContext *cx, JS::Handle wrapper, - JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle wrapper, JS::Handle id, JS::MutableHandle desc) const MOZ_OVERRIDE; + virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle wrapper, + JS::AutoIdVector &props) const MOZ_OVERRIDE; }; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.cpp 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.cpp 2014-11-26 21:46:04.000000000 +0000 @@ -60,10 +60,10 @@ bool WaiveXrayWrapper::iterate(JSContext *cx, HandleObject proxy, unsigned flags, - MutableHandleValue vp) const + MutableHandleObject objp) const { - return CrossCompartmentWrapper::iterate(cx, proxy, flags, vp) && - WrapperFactory::WaiveXrayAndWrap(cx, vp); + return CrossCompartmentWrapper::iterate(cx, proxy, flags, objp) && + (!objp || WrapperFactory::WaiveXrayAndWrap(cx, objp)); } bool diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.h 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/WaiveXrayWrapper.h 2014-11-26 21:46:04.000000000 +0000 @@ -30,7 +30,7 @@ const JS::CallArgs &args) const MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, JS::Handle proxy, unsigned flags, - JS::MutableHandle vp) const MOZ_OVERRIDE; + JS::MutableHandle objp) const MOZ_OVERRIDE; virtual bool nativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl, JS::CallArgs args) const MOZ_OVERRIDE; virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle wrapper, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/XrayWrapper.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/XrayWrapper.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/XrayWrapper.cpp 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/XrayWrapper.cpp 2014-11-26 21:46:04.000000000 +0000 @@ -2039,7 +2039,7 @@ AutoIdVector &props) const { assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE); - return enumerate(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props); + return getPropertyKeys(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props); } template @@ -2065,37 +2065,6 @@ template bool -XrayWrapper::enumerate(JSContext *cx, HandleObject wrapper, unsigned flags, - AutoIdVector &props) const -{ - assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE); - - // Enumerate expando properties first. Note that the expando object lives - // in the target compartment. - RootedObject target(cx, Traits::singleton.getTargetObject(wrapper)); - RootedObject expando(cx); - if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando)) - return false; - - if (expando) { - JSAutoCompartment ac(cx, expando); - if (!js::GetPropertyKeys(cx, expando, flags, &props)) - return false; - } - - return Traits::singleton.enumerateNames(cx, wrapper, flags, props); -} - -template -bool -XrayWrapper::enumerate(JSContext *cx, HandleObject wrapper, - AutoIdVector &props) const -{ - return enumerate(cx, wrapper, 0, props); -} - -template -bool XrayWrapper::get(JSContext *cx, HandleObject wrapper, HandleObject receiver, HandleId id, MutableHandleValue vp) const @@ -2149,11 +2118,19 @@ template bool +XrayWrapper::getEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper, + AutoIdVector &props) const +{ + return getPropertyKeys(cx, wrapper, 0, props); +} + +template +bool XrayWrapper::iterate(JSContext *cx, HandleObject wrapper, - unsigned flags, MutableHandleValue vp) const + unsigned flags, MutableHandleObject objp) const { // Skip our Base if it isn't already ProxyHandler. - return js::BaseProxyHandler::iterate(cx, wrapper, flags, vp); + return js::BaseProxyHandler::iterate(cx, wrapper, flags, objp); } template @@ -2266,6 +2243,29 @@ return true; } +template +bool +XrayWrapper::getPropertyKeys(JSContext *cx, HandleObject wrapper, unsigned flags, + AutoIdVector &props) const +{ + assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE); + + // Enumerate expando properties first. Note that the expando object lives + // in the target compartment. + RootedObject target(cx, Traits::singleton.getTargetObject(wrapper)); + RootedObject expando(cx); + if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando)) + return false; + + if (expando) { + JSAutoCompartment ac(cx, expando); + if (!js::GetPropertyKeys(cx, expando, flags, &props)) + return false; + } + + return Traits::singleton.enumerateNames(cx, wrapper, flags, props); +} + /* * The Permissive / Security variants should be used depending on whether the * compartment of the wrapper is guranteed to subsume the compartment of the diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/XrayWrapper.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/XrayWrapper.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/js/xpconnect/wrappers/XrayWrapper.h 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/js/xpconnect/wrappers/XrayWrapper.h 2014-11-26 21:46:04.000000000 +0000 @@ -413,7 +413,6 @@ JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, JS::Handle wrapper, JS::Handle id, bool *bp) const MOZ_OVERRIDE; - virtual bool enumerate(JSContext *cx, JS::Handle wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, JS::MutableHandleObject protop) const MOZ_OVERRIDE; virtual bool setPrototypeOf(JSContext *cx, JS::HandleObject wrapper, @@ -440,8 +439,10 @@ bool *bp) const MOZ_OVERRIDE; virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE; + virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle wrapper, + JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, JS::Handle wrapper, unsigned flags, - JS::MutableHandle vp) const MOZ_OVERRIDE; + JS::MutableHandle objp) const MOZ_OVERRIDE; virtual const char *className(JSContext *cx, JS::HandleObject proxy) const MOZ_OVERRIDE; virtual bool defaultValue(JSContext *cx, JS::HandleObject wrapper, @@ -473,8 +474,8 @@ } protected: - bool enumerate(JSContext *cx, JS::Handle wrapper, unsigned flags, - JS::AutoIdVector &props) const; + bool getPropertyKeys(JSContext *cx, JS::Handle wrapper, unsigned flags, + JS::AutoIdVector &props) const; }; #define PermissiveXrayXPCWN xpc::XrayWrapper @@ -512,7 +513,7 @@ virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle proxy, JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, JS::Handle proxy, unsigned flags, - JS::MutableHandle vp) const MOZ_OVERRIDE; + JS::MutableHandle objp) const MOZ_OVERRIDE; }; extern const SandboxProxyHandler sandboxProxyHandler; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/419985.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/419985.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/419985.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/419985.html 2014-11-26 21:46:05.000000000 +0000 @@ -0,0 +1,29 @@ + + +Crash [@ nsView::~nsView()] with onload focusing and removing window + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/429881.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/429881.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/429881.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/429881.html 2014-11-26 21:46:05.000000000 +0000 @@ -0,0 +1,6 @@ + + + +
+B
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/818454.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/818454.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/818454.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/818454.html 2014-11-26 21:46:05.000000000 +0000 @@ -0,0 +1,24 @@ +>
>
+>>>
+ 9Z 1CU %b 1 *v +` mMx#[j +>>
+>>
>> \ No newline at end of file diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/crashtests.list thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/crashtests.list --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/crashtests/crashtests.list 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/crashtests/crashtests.list 2014-11-26 21:46:05.000000000 +0000 @@ -231,6 +231,7 @@ load 414175-1.xul load 415503.xhtml load 416107.xhtml +HTTP load 419985.html load 420031-1.html load 420213-1.html load 420219-1.html @@ -247,6 +248,7 @@ load 429088-2.html load 429780-1.xhtml load 429865-1.html +load 429881.html load 430569-1.html load 430569-2.html load 432752-1.svg @@ -421,6 +423,7 @@ load 812665.html load 813372-1.html asserts(0-4) load 817219.html # bug 623436 +load 818454.html asserts-if(gtk2Widget,0-1) load 822865.html # bug 540078 load 824862.html load 826163.html diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/DisplayItemClip.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/DisplayItemClip.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/DisplayItemClip.cpp 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/DisplayItemClip.cpp 2014-11-26 21:46:04.000000000 +0000 @@ -6,6 +6,8 @@ #include "DisplayItemClip.h" #include "gfxContext.h" +#include "gfxUtils.h" +#include "mozilla/gfx/2D.h" #include "mozilla/gfx/PathHelpers.h" #include "nsPresContext.h" #include "nsCSSRendering.h" @@ -118,24 +120,34 @@ } void -DisplayItemClip::DrawRoundedRectsTo(gfxContext* aContext, - int32_t A2D, - uint32_t aBegin, uint32_t aEnd) const +DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext, + const Color& aColor, + int32_t aAppUnitsPerDevPixel, + uint32_t aBegin, + uint32_t aEnd) const { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); aEnd = std::min(aEnd, mRoundedClipRects.Length()); - if (aEnd - aBegin == 0) + if (aBegin >= aEnd) { return; + } + + // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any: + ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, aBegin, aEnd - 1); - // If there is just one rounded rect we can just fill it, if there are more then we - // must clip the rest to get the intersection of clips - ApplyRoundedRectClipsTo(aContext, A2D, aBegin, aEnd - 1); - RefPtr roundedRect = - MakeRoundedRectPath(aDrawTarget, A2D, mRoundedClipRects[aEnd - 1]); - aContext->SetPath(roundedRect); - aContext->Fill(); + // Now fill the rect at |aEnd - 1|: + RefPtr roundedRect = MakeRoundedRectPath(aDrawTarget, + aAppUnitsPerDevPixel, + mRoundedClipRects[aEnd - 1]); + ColorPattern color(ToDeviceColor(aColor)); + aDrawTarget.Fill(roundedRect, color); + + // Finally, pop any clips that we may have pushed: + for (uint32_t i = aBegin; i < aEnd - 1; ++i) { + aContext->PopClip(); + } } TemporaryRef diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/DisplayItemClip.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/DisplayItemClip.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/DisplayItemClip.h 2014-11-14 09:37:33.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/DisplayItemClip.h 2014-11-26 21:46:04.000000000 +0000 @@ -32,6 +32,7 @@ * SVG clip-path), including no clipping at all. */ class DisplayItemClip { + typedef mozilla::gfx::Color Color; typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::Path Path; @@ -85,8 +86,11 @@ uint32_t aBegin, uint32_t aEnd) const; // Draw (fill) the rounded rects in this clip to aContext - void DrawRoundedRectsTo(gfxContext* aContext, int32_t A2D, - uint32_t aBegin, uint32_t aEnd) const; + void FillIntersectionOfRoundedRectClips(gfxContext* aContext, + const Color& aColor, + int32_t aAppUnitsPerDevPixel, + uint32_t aBegin, + uint32_t aEnd) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext mozilla::TemporaryRef MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/FrameLayerBuilder.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/FrameLayerBuilder.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/FrameLayerBuilder.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/FrameLayerBuilder.cpp 2014-11-26 21:46:04.000000000 +0000 @@ -268,6 +268,20 @@ mNewChildLayersIndex(-1), mAllDrawingAbove(false) {} + +#ifdef MOZ_DUMP_PAINTING + /** + * Keep track of important decisions for debugging. + */ + nsAutoCString mLog; + + #define FLB_LOG_PAINTED_LAYER_DECISION(tld, ...) \ + tld->mLog.AppendPrintf("\t\t\t\t"); \ + tld->mLog.AppendPrintf(__VA_ARGS__); +#else + #define FLB_LOG_PAINTED_LAYER_DECISION(...) +#endif + /** * Record that an item has been added to the PaintedLayer, so we * need to update our regions. @@ -290,16 +304,16 @@ const nsIFrame* GetAnimatedGeometryRoot() { return mAnimatedGeometryRoot; } /** - * Add aHitRegion, aMaybeHitRegion, and aDispatchToContentHitRegion to the - * hit regions for this PaintedLayer. + * Add the given hit regions to the hit regions to the hit retions for this + * PaintedLayer. */ - void AccumulateEventRegions(const nsRegion& aHitRegion, - const nsRegion& aMaybeHitRegion, - const nsRegion& aDispatchToContentHitRegion) + void AccumulateEventRegions(nsDisplayLayerEventRegions* aEventRegions) { - mHitRegion.Or(mHitRegion, aHitRegion); - mMaybeHitRegion.Or(mMaybeHitRegion, aMaybeHitRegion); - mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aDispatchToContentHitRegion); + FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating event regions %p against tld=%p\n", aEventRegions, this); + + mHitRegion.Or(mHitRegion, aEventRegions->HitRegion()); + mMaybeHitRegion.Or(mMaybeHitRegion, aEventRegions->MaybeHitRegion()); + mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aEventRegions->DispatchToContentHitRegion()); } /** @@ -374,20 +388,6 @@ return mFixedPosFrameForLayerData != nullptr; } -#ifdef MOZ_DUMP_PAINTING - - /** - * Keep track of important decisions for debugging. - */ - nsAutoCString mLog; - - #define FLB_LOG_PAINTED_LAYER_DECISION(tld, ...) \ - tld->mLog.AppendPrintf("\t\t\t\t"); \ - tld->mLog.AppendPrintf(__VA_ARGS__); -#else - #define FLB_LOG_PAINTED_LAYER_DECISION(...) -#endif - /** * The region of visible content in the layer, relative to the * container layer (which is at the snapped top-left of the display @@ -3055,9 +3055,7 @@ if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) { nsDisplayLayerEventRegions* eventRegions = static_cast(item); - paintedLayerData->AccumulateEventRegions(eventRegions->HitRegion(), - eventRegions->MaybeHitRegion(), - eventRegions->DispatchToContentHitRegion()); + paintedLayerData->AccumulateEventRegions(eventRegions); } else { // check to see if the new item has rounded rect clips in common with // other items in the layer @@ -4407,17 +4405,17 @@ } DrawTarget *dt = aContext->GetDrawTarget(); - return dt->GetBackendType() == BackendType::DIRECT2D; + return !dt->SupportsRegionClipping(); } -static void DrawForcedBackgroundColor(gfxContext* aContext, Layer* aLayer, nscolor aBackgroundColor) +static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget, + Layer* aLayer, nscolor + aBackgroundColor) { if (NS_GET_A(aBackgroundColor) > 0) { nsIntRect r = aLayer->GetVisibleRegion().GetBounds(); - aContext->NewPath(); - aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height)); - aContext->SetColor(gfxRGBA(aBackgroundColor)); - aContext->Fill(); + ColorPattern color(ToDeviceColor(aBackgroundColor)); + aDrawTarget.FillRect(Rect(r.x, r.y, r.width, r.height), color); } } @@ -4457,6 +4455,8 @@ const nsIntRegion& aRegionToInvalidate, void* aCallbackData) { + DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); + PROFILER_LABEL("FrameLayerBuilder", "DrawPaintedLayer", js::ProfileEntry::Category::GRAPHICS); @@ -4488,7 +4488,8 @@ gfxUtils::ClipToRegion(aContext, aRegionToDraw); } - DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor); + DrawForcedBackgroundColor(aDrawTarget, aLayer, + userData->mForcedBackgroundColor); } if (NS_GET_A(userData->mFontSmoothingBackgroundColor) > 0) { @@ -4522,7 +4523,8 @@ aContext->Rectangle(*iterRect); aContext->Clip(); - DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor); + DrawForcedBackgroundColor(aDrawTarget, aLayer, + userData->mForcedBackgroundColor); // Apply the residual transform if it has been enabled, to ensure that // snapping when we draw into aContext exactly matches the ideal transform. @@ -4720,11 +4722,11 @@ context->Multiply(ThebesMatrix(imageTransform)); // paint the clipping rects with alpha to create the mask - context->SetColor(gfxRGBA(1, 1, 1, 1)); - aClip.DrawRoundedRectsTo(context, - newData.mAppUnitsPerDevPixel, - 0, - aRoundedRectClipCount); + aClip.FillIntersectionOfRoundedRectClips(context, + Color(1.f, 1.f, 1.f, 1.f), + newData.mAppUnitsPerDevPixel, + 0, + aRoundedRectClipCount); RefPtr surface = dt->Snapshot(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsBidiPresUtils.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsBidiPresUtils.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsBidiPresUtils.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsBidiPresUtils.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -358,10 +358,10 @@ frame && aNumFramesOnLine--; frame = frame->GetNextSibling()) { AppendFrame(frame); - uint8_t level = nsBidiPresUtils::GetFrameEmbeddingLevel(frame); + nsBidiLevel level = nsBidiPresUtils::GetFrameEmbeddingLevel(frame); mLevels.AppendElement(level); mIndexMap.AppendElement(0); - if (level & 1) { + if (IS_LEVEL_RTL(level)) { hasRTLFrames = true; } } @@ -658,7 +658,7 @@ nsresult rv = aBpd->SetPara(); NS_ENSURE_SUCCESS(rv, rv); - uint8_t embeddingLevel = aBpd->GetParaLevel(); + nsBidiLevel embeddingLevel = aBpd->GetParaLevel(); rv = aBpd->CountRuns(&runCount); NS_ENSURE_SUCCESS(rv, rv); @@ -1539,7 +1539,7 @@ for (; index != limit; index += step) { frame = aBld->VisualFrameAt(index); RepositionFrame(frame, - !(aBld->mLevels[aBld->mIndexMap[index]] & 1), + !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])), start, &continuationStates, aLineWM, @@ -1675,9 +1675,9 @@ nsresult nsBidiPresUtils::FormatUnicodeText(nsPresContext* aPresContext, char16_t* aText, - int32_t& aTextLength, - nsCharType aCharType, - bool aIsOddLevel) + int32_t& aTextLength, + nsCharType aCharType, + nsBidiDirection aDir) { nsresult rv = NS_OK; // ahmed @@ -1877,8 +1877,7 @@ uint32_t visualStart = 0; uint8_t charType; uint8_t prevType = eCharType_LeftToRight; - nsBidiLevel level; - + for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve) { aPosResolve[nPosResolve].visualIndex = kNotFound; @@ -1892,10 +1891,12 @@ if (NS_FAILED(rv)) return rv; + nsBidiLevel level; rv = aBidiEngine->GetLogicalRun(start, &limit, &level); if (NS_FAILED(rv)) return rv; + dir = DIRECTION_FROM_LEVEL(level); int32_t subRunLength = limit - start; int32_t lineOffset = start; int32_t typeLimit = std::min(limit, aLength); @@ -1914,8 +1915,8 @@ * x-coordinate of the end of the run for the start of the next run. */ - if (level & 1) { - aprocessor.SetText(aText + start, subRunLength, nsBidiDirection(level & 1)); + if (dir == NSBIDI_RTL) { + aprocessor.SetText(aText + start, subRunLength, dir); width = aprocessor.GetWidth(); xOffset += width; xEndRun = xOffset; @@ -1925,18 +1926,18 @@ // CalculateCharType can increment subRunCount if the run // contains mixed character types CalculateCharType(aBidiEngine, aText, lineOffset, typeLimit, subRunLimit, subRunLength, subRunCount, charType, prevType); - + nsAutoString runVisualText; runVisualText.Assign(aText + start, subRunLength); if (int32_t(runVisualText.Length()) < subRunLength) return NS_ERROR_OUT_OF_MEMORY; - FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), subRunLength, - (nsCharType)charType, level & 1); + FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), + subRunLength, (nsCharType)charType, dir); - aprocessor.SetText(runVisualText.get(), subRunLength, nsBidiDirection(level & 1)); + aprocessor.SetText(runVisualText.get(), subRunLength, dir); width = aprocessor.GetWidth(); totalWidth += width; - if (level & 1) { + if (dir == NSBIDI_RTL) { xOffset -= width; } if (aMode == MODE_DRAW) { @@ -2007,7 +2008,7 @@ // The position in the text where this run's "left part" begins. const char16_t* visualLeftPart; const char16_t* visualRightSide; - if (level & 1) { + if (dir == NSBIDI_RTL) { // One day, son, this could all be replaced with mBidiEngine.GetVisualIndex ... posResolve->visualIndex = visualStart + (subRunLength - (posResolve->logicalIndex + 1 - start)); // Skipping to the "left part". @@ -2024,16 +2025,16 @@ } // The delta between the start of the run and the left part's end. int32_t visualLeftLength = posResolve->visualIndex - visualStart; - aprocessor.SetText(visualLeftPart, visualLeftLength, nsBidiDirection(level & 1)); + aprocessor.SetText(visualLeftPart, visualLeftLength, dir); subWidth = aprocessor.GetWidth(); - aprocessor.SetText(visualRightSide, visualLeftLength + 1, nsBidiDirection(level & 1)); + aprocessor.SetText(visualRightSide, visualLeftLength + 1, dir); posResolve->visualLeftTwips = xOffset + subWidth; posResolve->visualWidth = aprocessor.GetWidth() - subWidth; } } } - if (!(level & 1)) { + if (dir == NSBIDI_LTR) { xOffset += width; } @@ -2042,10 +2043,10 @@ subRunLimit = typeLimit; subRunLength = typeLimit - lineOffset; } // while - if (level & 1) { + if (dir == NSBIDI_RTL) { xOffset = xEndRun; } - + visualStart += length; } // for @@ -2075,8 +2076,8 @@ } virtual void SetText(const char16_t* aText, - int32_t aLength, - nsBidiDirection aDirection) MOZ_OVERRIDE + int32_t aLength, + nsBidiDirection aDirection) MOZ_OVERRIDE { mFontMetrics->SetTextRunRTL(aDirection==NSBIDI_RTL); mText = aText; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsBidiPresUtils.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsBidiPresUtils.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsBidiPresUtils.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsBidiPresUtils.h 2014-11-26 21:46:05.000000000 +0000 @@ -107,15 +107,15 @@ * @remark The reason that the function gives a string instead of an index * is that ProcessText copies and modifies the string passed to it, so * passing an index would be impossible. - * + * * @param aText The string of text. * @param aLength The length of the string of text. * @param aDirection The direction of the text. The string will never have * mixed direction. */ virtual void SetText(const char16_t* aText, - int32_t aLength, - nsBidiDirection aDirection) = 0; + int32_t aLength, + nsBidiDirection aDirection) = 0; /** * Returns the measured width of the text given in SetText. If SetText was @@ -171,11 +171,11 @@ * * @lina 06/18/2000 */ - static nsresult FormatUnicodeText(nsPresContext* aPresContext, - char16_t* aText, + static nsresult FormatUnicodeText(nsPresContext* aPresContext, + char16_t* aText, int32_t& aTextLength, nsCharType aCharType, - bool aIsOddLevel); + nsBidiDirection aDir); /** * Reorder plain text using the Unicode Bidi algorithm and send it to @@ -286,6 +286,30 @@ */ static nsBidiLevel GetFrameBaseLevel(nsIFrame* aFrame); + /** + * Get an nsBidiDirection representing the direction implied by the + * bidi base level of the frame. + * @return NSBIDI_LTR (left-to-right) or NSBIDI_RTL (right-to-left) + * NSBIDI_MIXED will never be returned. + */ + static nsBidiDirection ParagraphDirection(nsIFrame* aFrame) { + return DIRECTION_FROM_LEVEL(GetFrameBaseLevel(aFrame)); + } + + /** + * Get an nsBidiDirection representing the direction implied by the + * bidi embedding level of the frame. + * @return NSBIDI_LTR (left-to-right) or NSBIDI_RTL (right-to-left) + * NSBIDI_MIXED will never be returned. + */ + static nsBidiDirection FrameDirection(nsIFrame* aFrame) { + return DIRECTION_FROM_LEVEL(GetFrameEmbeddingLevel(aFrame)); + } + + static bool IsFrameInParagraphDirection(nsIFrame* aFrame) { + return ParagraphDirection(aFrame) == FrameDirection(aFrame); + } + enum Mode { MODE_DRAW, MODE_MEASURE }; /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCaret.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCaret.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCaret.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCaret.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -381,7 +381,7 @@ nsIContent* contentNode = focusNode->AsContent(); nsFrameSelection* frameSelection = aSelection->GetFrameSelection(); - uint8_t bidiLevel = frameSelection->GetCaretBidiLevel(); + nsBidiLevel bidiLevel = frameSelection->GetCaretBidiLevel(); nsIFrame* frame; nsresult rv = nsCaret::GetCaretFrameForNodeOffset( frameSelection, contentNode, focusOffset, @@ -607,12 +607,12 @@ } } -nsresult +nsresult nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection, nsIContent* aContentNode, int32_t aOffset, CaretAssociationHint aFrameHint, - uint8_t aBidiLevel, + nsBidiLevel aBidiLevel, nsIFrame** aReturnFrame, int32_t* aReturnOffset) { @@ -646,7 +646,6 @@ // ------------------ // NS_STYLE_DIRECTION_LTR : LTR or Default // NS_STYLE_DIRECTION_RTL - // NS_STYLE_DIRECTION_INHERIT if (IsBidiUI()) { // If there has been a reflow, take the caret Bidi level to be the level of the current frame @@ -657,8 +656,8 @@ int32_t end; nsIFrame* frameBefore; nsIFrame* frameAfter; - uint8_t levelBefore; // Bidi level of the character before the caret - uint8_t levelAfter; // Bidi level of the character after the caret + nsBidiLevel levelBefore; // Bidi level of the character before the caret + nsBidiLevel levelAfter; // Bidi level of the character after the caret theFrame->GetOffsets(start, end); if (start == 0 || end == 0 || start == theFrameOffset || end == theFrameOffset) @@ -679,8 +678,10 @@ aBidiLevel = std::max(aBidiLevel, std::min(levelBefore, levelAfter)); // rule c3 aBidiLevel = std::min(aBidiLevel, std::max(levelBefore, levelAfter)); // rule c4 if (aBidiLevel == levelBefore // rule c1 - || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && !((aBidiLevel ^ levelBefore) & 1)) // rule c5 - || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && !((aBidiLevel ^ levelBefore) & 1))) // rule c9 + || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelBefore)) // rule c5 + || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelBefore))) // rule c9 { if (theFrame != frameBefore) { @@ -696,10 +697,12 @@ // so we stay with the current frame. // Exception: when the first frame on the line has a different Bidi level from the paragraph level, there is no // real frame for the caret to be in. We have to find the visually first frame on the line. - uint8_t baseLevel = NS_GET_BASE_LEVEL(frameAfter); + nsBidiLevel baseLevel = NS_GET_BASE_LEVEL(frameAfter); if (baseLevel != levelAfter) { - nsPeekOffsetStruct pos(eSelectBeginLine, eDirPrevious, 0, 0, false, true, false, true); + nsPeekOffsetStruct pos(eSelectBeginLine, eDirPrevious, 0, + nsPoint(0, 0), false, true, false, + true); if (NS_SUCCEEDED(frameAfter->PeekOffset(&pos))) { theFrame = pos.mResultFrame; theFrameOffset = pos.mContentOffset; @@ -709,8 +712,10 @@ } } else if (aBidiLevel == levelAfter // rule c2 - || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && !((aBidiLevel ^ levelAfter) & 1)) // rule c6 - || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && !((aBidiLevel ^ levelAfter) & 1))) // rule c10 + || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelAfter)) // rule c6 + || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelAfter))) // rule c10 { if (theFrame != frameAfter) { @@ -727,10 +732,12 @@ // so we stay with the current frame. // Exception: when the last frame on the line has a different Bidi level from the paragraph level, there is no // real frame for the caret to be in. We have to find the visually last frame on the line. - uint8_t baseLevel = NS_GET_BASE_LEVEL(frameBefore); + nsBidiLevel baseLevel = NS_GET_BASE_LEVEL(frameBefore); if (baseLevel != levelBefore) { - nsPeekOffsetStruct pos(eSelectEndLine, eDirNext, 0, 0, false, true, false, true); + nsPeekOffsetStruct pos(eSelectEndLine, eDirNext, 0, + nsPoint(0, 0), false, true, false, + true); if (NS_SUCCEEDED(frameBefore->PeekOffset(&pos))) { theFrame = pos.mResultFrame; theFrameOffset = pos.mContentOffset; @@ -740,33 +747,33 @@ } } else if (aBidiLevel > levelBefore && aBidiLevel < levelAfter // rule c7/8 - && !((levelBefore ^ levelAfter) & 1) // before and after have the same parity - && ((aBidiLevel ^ levelAfter) & 1)) // caret has different parity + && IS_SAME_DIRECTION(levelBefore, levelAfter) // before and after have the same parity + && !IS_SAME_DIRECTION(aBidiLevel, levelAfter)) // caret has different parity { if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel(frameAfter, eDirNext, aBidiLevel, &theFrame))) { theFrame->GetOffsets(start, end); levelAfter = NS_GET_EMBEDDING_LEVEL(theFrame); - if (aBidiLevel & 1) // c8: caret to the right of the rightmost character - theFrameOffset = (levelAfter & 1) ? start : end; + if (IS_LEVEL_RTL(aBidiLevel)) // c8: caret to the right of the rightmost character + theFrameOffset = IS_LEVEL_RTL(levelAfter) ? start : end; else // c7: caret to the left of the leftmost character - theFrameOffset = (levelAfter & 1) ? end : start; + theFrameOffset = IS_LEVEL_RTL(levelAfter) ? end : start; } } else if (aBidiLevel < levelBefore && aBidiLevel > levelAfter // rule c11/12 - && !((levelBefore ^ levelAfter) & 1) // before and after have the same parity - && ((aBidiLevel ^ levelAfter) & 1)) // caret has different parity + && IS_SAME_DIRECTION(levelBefore, levelAfter) // before and after have the same parity + && !IS_SAME_DIRECTION(aBidiLevel, levelAfter)) // caret has different parity { if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel(frameBefore, eDirPrevious, aBidiLevel, &theFrame))) { theFrame->GetOffsets(start, end); levelBefore = NS_GET_EMBEDDING_LEVEL(theFrame); - if (aBidiLevel & 1) // c12: caret to the left of the leftmost character - theFrameOffset = (levelBefore & 1) ? end : start; + if (IS_LEVEL_RTL(aBidiLevel)) // c12: caret to the left of the leftmost character + theFrameOffset = IS_LEVEL_RTL(levelBefore) ? end : start; else // c11: caret to the right of the rightmost character - theFrameOffset = (levelBefore & 1) ? start : end; + theFrameOffset = IS_LEVEL_RTL(levelBefore) ? start : end; } - } + } } } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSFrameConstructor.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSFrameConstructor.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSFrameConstructor.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSFrameConstructor.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -611,30 +611,6 @@ aParent->SetInitialChildList(kPrincipalList, temp); } -static nsContainerFrame* -GetContentInsertionFrameFor(nsIContent* aContent) -{ - // Get the primary frame associated with the content - nsIFrame* frame = aContent->GetPrimaryFrame(); - - if (!frame) - return nullptr; - - // If the content of the frame is not the desired content then this is not - // really a frame for the desired content. - // XXX This check is needed due to bug 135040. Remove it once that's fixed. - if (frame->GetContent() != aContent) { - return nullptr; - } - - nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame(); - - NS_ASSERTION(!insertionFrame || insertionFrame == frame || !frame->IsLeaf(), - "The insertion frame is the primary frame or the primary frame isn't a leaf"); - - return insertionFrame; -} - // ----------------------------------------------------------- // Structure used when constructing formatting object trees. @@ -2288,8 +2264,9 @@ // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them // all anyway, and involve an extra walk down the frame construction item // list. - if (!aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) || - aParentFrame->IsGeneratedContentFrame() || + if ((aParentFrame && + (!aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) || + aParentFrame->IsGeneratedContentFrame())) || !aChildContent->IsNodeOfType(nsINode::eTEXT)) { return true; } @@ -2597,7 +2574,8 @@ newFrame = frameItems.FirstChild(); NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames"); } else { - MOZ_ASSERT(display->mDisplay == NS_STYLE_DISPLAY_BLOCK, + MOZ_ASSERT(display->mDisplay == NS_STYLE_DISPLAY_BLOCK || + display->mDisplay == NS_STYLE_DISPLAY_CONTENTS, "Unhandled display type for root element"); contentFrame = NS_NewBlockFormattingContext(mPresShell, styleContext); nsFrameItems frameItems; @@ -2624,7 +2602,7 @@ // Figure out which frame has the main style for the document element, // assigning it to mRootElementStyleFrame. // Backgrounds should be propagated from that frame to the viewport. - mRootElementStyleFrame = contentFrame->GetParentStyleContextFrame(); + contentFrame->GetParentStyleContext(&mRootElementStyleFrame); bool isChild = mRootElementStyleFrame && mRootElementStyleFrame->GetParent() == contentFrame; if (!isChild) { @@ -3704,19 +3682,22 @@ return; } - nsStyleContext* const styleContext = aItem.mStyleContext; - const nsStyleDisplay* display = styleContext->StyleDisplay(); nsIContent* const content = aItem.mContent; + nsIContent* parent = content->GetParent(); + + // Push display:contents ancestors. + AutoDisplayContentsAncestorPusher adcp(aState.mTreeMatchContext, + aState.mPresContext, parent); // Get the parent of the content and check if it is a XBL children element. // Push the children element as an ancestor here because it does // not have a frame and would not otherwise be pushed as an ancestor. It is // necessary to do so in order to correctly handle style resolution on - // descendants. - nsIContent* parent = content->GetParent(); + // descendants. (If !adcp.IsEmpty() then it was already pushed by + // AutoDisplayContentsAncestorPusher above.) TreeMatchContext::AutoAncestorPusher insertionPointPusher(aState.mTreeMatchContext); - if (parent && nsContentUtils::IsContentInsertionPoint(parent)) { + if (adcp.IsEmpty() && parent && nsContentUtils::IsContentInsertionPoint(parent)) { if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { insertionPointPusher.PushAncestorAndStyleScope(parent); } else { @@ -3742,6 +3723,8 @@ nsIFrame* newFrame; nsIFrame* primaryFrame; + nsStyleContext* const styleContext = aItem.mStyleContext; + const nsStyleDisplay* display = styleContext->StyleDisplay(); if (bits & FCDATA_FUNC_IS_FULL_CTOR) { newFrame = (this->*(data->mFullConstructor))(aState, aItem, aParentFrame, @@ -3992,6 +3975,7 @@ NS_ASSERTION(creator, "How can that happen if we have nodes to construct frames for?"); + InsertionPoint insertion(aParentFrame, aParent); for (uint32_t i=0; i < count; i++) { nsIContent* content = newAnonymousItems[i].mContent; NS_ASSERTION(content, "null anonymous content?"); @@ -4015,7 +3999,7 @@ TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext); - AddFrameConstructionItems(aState, content, true, aParentFrame, items); + AddFrameConstructionItems(aState, content, true, insertion, items); } ConstructFramesFromItemList(aState, items, aParentFrame, aChildItems); } @@ -4508,7 +4492,8 @@ // block-level. NS_ASSERTION(!(aDisplay->IsFloatingStyle() || aDisplay->IsAbsolutelyPositionedStyle()) || - aDisplay->IsBlockOutsideStyle(), + aDisplay->IsBlockOutsideStyle() || + aDisplay->mDisplay == NS_STYLE_DISPLAY_CONTENTS, "Style system did not apply CSS2.1 section 9.7 fixups"); // If this is "body", try propagating its scroll style to the viewport @@ -4649,9 +4634,16 @@ { NS_STYLE_DISPLAY_TABLE_CELL, FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow), - &nsCSSFrameConstructor::ConstructTableCell) } + &nsCSSFrameConstructor::ConstructTableCell) }, + { NS_STYLE_DISPLAY_CONTENTS, + FULL_CTOR_FCDATA(FCDATA_IS_CONTENTS, nullptr/*never called*/) } }; + // See the mDisplay fixup code in nsRuleNode::ComputeDisplayData. + MOZ_ASSERT(aDisplay->mDisplay != NS_STYLE_DISPLAY_CONTENTS || + !aElement->IsRootOfNativeAnonymousSubtree(), + "display:contents on anonymous content is unsupported"); + return FindDataByInt(aDisplay->mDisplay, aElement, aStyleContext, sDisplayData, ArrayLength(sDisplayData)); @@ -4765,27 +4757,48 @@ already_AddRefed nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame, - nsIContent* aContent, + nsIContent* aContainer, + nsIContent* aChild, nsFrameConstructorState* aState) { - nsStyleContext* parentStyleContext = nullptr; - NS_ASSERTION(aContent->GetParent(), "Must have parent here"); + MOZ_ASSERT(aContainer, "Must have parent here"); + // XXX uncomment when bug 1089223 is fixed: + // MOZ_ASSERT(aContainer == aChild->GetFlattenedTreeParent()); + nsStyleContext* parentStyleContext = GetDisplayContentsStyleFor(aContainer); + if (MOZ_LIKELY(!parentStyleContext)) { + aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nullptr); + if (aParentFrame) { + MOZ_ASSERT(aParentFrame->GetContent() == aContainer); + // Resolve the style context based on the content object and the parent + // style context + parentStyleContext = aParentFrame->StyleContext(); + } else { + // Perhaps aParentFrame is a canvasFrame and we're replicating + // fixed-pos frames. + // XXX should we create a way to tell ConstructFrame which style + // context to use, and pass it the style context for the + // previous page's fixed-pos frame? + } + } - aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nullptr); + return ResolveStyleContext(parentStyleContext, aChild, aState); +} - if (aParentFrame) { - // Resolve the style context based on the content object and the parent - // style context - parentStyleContext = aParentFrame->StyleContext(); - } else { - // Perhaps aParentFrame is a canvasFrame and we're replicating - // fixed-pos frames. - // XXX should we create a way to tell ConstructFrame which style - // context to use, and pass it the style context for the - // previous page's fixed-pos frame? - } +already_AddRefed +nsCSSFrameConstructor::ResolveStyleContext(nsIFrame* aParentFrame, + nsIContent* aChild, + nsFrameConstructorState* aState) +{ + return ResolveStyleContext(aParentFrame, aChild->GetFlattenedTreeParent(), aChild, aState); +} - return ResolveStyleContext(parentStyleContext, aContent, aState); +already_AddRefed +nsCSSFrameConstructor::ResolveStyleContext(const InsertionPoint& aInsertion, + nsIContent* aChild, + nsFrameConstructorState* aState) +{ + return ResolveStyleContext(aInsertion.mParentFrame, aInsertion.mContainer, + aChild, aState); } already_AddRefed @@ -5303,12 +5316,10 @@ true, nullptr); } -void -nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState, +bool +nsCSSFrameConstructor::ShouldCreateItemsForChild(nsFrameConstructorState& aState, nsIContent* aContent, - bool aSuppressWhiteSpaceOptimizations, - nsContainerFrame* aParentFrame, - FrameConstructionItemList& aItems) + nsContainerFrame* aParentFrame) { aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME); if (aContent->IsElement()) { @@ -5329,40 +5340,70 @@ !aState.mCreatingExtraFrames) { NS_ERROR("asked to create frame construction item for a node that already " "has a frame"); - return; + return false; } // don't create a whitespace frame if aParent doesn't want it if (!NeedFrameFor(aState, aParentFrame, aContent)) { - return; + return false; } // never create frames for comments or PIs if (aContent->IsNodeOfType(nsINode::eCOMMENT) || - aContent->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) - return; + aContent->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) { + return false; + } - nsRefPtr styleContext; - styleContext = ResolveStyleContext(aParentFrame, aContent, &aState); + return true; +} +void +nsCSSFrameConstructor::DoAddFrameConstructionItems(nsFrameConstructorState& aState, + nsIContent* aContent, + nsStyleContext* aStyleContext, + bool aSuppressWhiteSpaceOptimizations, + nsContainerFrame* aParentFrame, + nsTArray* aAnonChildren, + FrameConstructionItemList& aItems) +{ uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK; - if (aParentFrame->IsSVGText()) { - flags |= ITEM_IS_WITHIN_SVG_TEXT; - } - if (aParentFrame->GetType() == nsGkAtoms::blockFrame && - aParentFrame->GetParent() && - aParentFrame->GetParent()->GetType() == nsGkAtoms::svgTextFrame) { - flags |= ITEM_ALLOWS_TEXT_PATH_CHILD; + if (aParentFrame) { + if (aParentFrame->IsSVGText()) { + flags |= ITEM_IS_WITHIN_SVG_TEXT; + } + if (aParentFrame->GetType() == nsGkAtoms::blockFrame && + aParentFrame->GetParent() && + aParentFrame->GetParent()->GetType() == nsGkAtoms::svgTextFrame) { + flags |= ITEM_ALLOWS_TEXT_PATH_CHILD; + } } AddFrameConstructionItemsInternal(aState, aContent, aParentFrame, aContent->Tag(), aContent->GetNameSpaceID(), aSuppressWhiteSpaceOptimizations, - styleContext, - flags, nullptr, + aStyleContext, + flags, aAnonChildren, aItems); } void +nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState, + nsIContent* aContent, + bool aSuppressWhiteSpaceOptimizations, + const InsertionPoint& aInsertion, + FrameConstructionItemList& aItems) +{ + nsContainerFrame* parentFrame = aInsertion.mParentFrame; + if (!ShouldCreateItemsForChild(aState, aContent, parentFrame)) { + return; + } + nsRefPtr styleContext = + ResolveStyleContext(aInsertion, aContent, &aState); + DoAddFrameConstructionItems(aState, aContent, styleContext, + aSuppressWhiteSpaceOptimizations, parentFrame, + nullptr, aItems); +} + +void nsCSSFrameConstructor::SetAsUndisplayedContent(nsFrameConstructorState& aState, FrameConstructionItemList& aList, nsIContent* aContent, @@ -5400,6 +5441,8 @@ NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT) || aContent->IsElement(), "Shouldn't get anything else here!"); + MOZ_ASSERT(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || + aContent->Tag() == nsGkAtoms::area); // The following code allows the user to specify the base tag // of an element using XBL. XUL and HTML objects (like boxes, menus, etc.) @@ -5571,6 +5614,66 @@ AddPageBreakItem(aContent, aStyleContext, aItems); } + if (MOZ_UNLIKELY(bits & FCDATA_IS_CONTENTS)) { + if (!GetDisplayContentsStyleFor(aContent)) { + MOZ_ASSERT(styleContext->GetPseudo() || !isGeneratedContent, + "Should have had pseudo type"); + aState.mFrameManager->SetDisplayContents(aContent, styleContext); + } else { + aState.mFrameManager->ChangeDisplayContents(aContent, styleContext); + } + + TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext); + if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { + ancestorPusher.PushAncestorAndStyleScope(aContent->AsElement()); + } else { + ancestorPusher.PushStyleScope(aContent->AsElement()); + } + + if (aParentFrame) { + aParentFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT); + } + CreateGeneratedContentItem(aState, aParentFrame, aContent, styleContext, + nsCSSPseudoElements::ePseudo_before, aItems); + + FlattenedChildIterator iter(aContent); + for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { + if (!ShouldCreateItemsForChild(aState, child, aParentFrame)) { + continue; + } + + // Get the parent of the content and check if it is a XBL children element + // (if the content is a children element then parent != aContent because the + // FlattenedChildIterator will transitively iterate through + // for default content). Push the children element as an ancestor here because + // it does not have a frame and would not otherwise be pushed as an ancestor. + nsIContent* parent = child->GetParent(); + MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children."); + TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext); + if (parent != aContent && parent->IsElement()) { + if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { + ancestorPusher.PushAncestorAndStyleScope(parent->AsElement()); + } else { + ancestorPusher.PushStyleScope(parent->AsElement()); + } + } + + nsRefPtr childContext = + ResolveStyleContext(styleContext, child, &aState); + DoAddFrameConstructionItems(aState, child, childContext, + aSuppressWhiteSpaceOptimizations, + aParentFrame, aAnonChildren, aItems); + } + aItems.SetParentHasNoXBLChildren(!iter.XBLInvolved()); + + CreateGeneratedContentItem(aState, aParentFrame, aContent, styleContext, + nsCSSPseudoElements::ePseudo_after, aItems); + if (canHavePageBreak && display->mBreakAfter) { + AddPageBreakItem(aContent, aStyleContext, aItems); + } + return; + } + FrameConstructionItem* item = aItems.AppendItem(data, aContent, aTag, aNameSpaceID, pendingBinding, styleContext.forget(), @@ -5677,24 +5780,17 @@ } static void -DestroyContent(void* aPropertyValue) -{ - nsIContent* content = static_cast(aPropertyValue); - content->UnbindFromTree(); - NS_RELEASE(content); -} - -NS_DECLARE_FRAME_PROPERTY(BeforeProperty, DestroyContent) -NS_DECLARE_FRAME_PROPERTY(AfterProperty, DestroyContent) - -static const FramePropertyDescriptor* -GenConPseudoToProperty(nsIAtom* aPseudo) +AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIContent* aContent) { - NS_ASSERTION(aPseudo == nsCSSPseudoElements::before || - aPseudo == nsCSSPseudoElements::after, - "Bad gen-con pseudo"); - return aPseudo == nsCSSPseudoElements::before ? BeforeProperty() - : AfterProperty(); + typedef nsAutoTArray T; + const FramePropertyDescriptor* prop = nsIFrame::GenConProperty(); + FrameProperties props = aOwnerFrame->Properties(); + T* value = static_cast(props.Get(prop)); + if (!value) { + value = new T; + props.Set(prop, value); + } + value->AppendElement(aContent); } /** @@ -5798,8 +5894,7 @@ // setting it on a table pseudo-frame inserted under that instead. That's // OK, though; we just need to do the property set so that the content will // get cleaned up when the frame is destroyed. - aParentFrame->Properties().Set(GenConPseudoToProperty(styleContext->GetPseudo()), - item.mContent); + ::AddGenConPseudoToFrame(aParentFrame, item.mContent); // Now that we've passed ownership of item.mContent to the frame, unset // our generated content flag so we don't release or unbind it ourselves. @@ -5934,21 +6029,70 @@ * frame before which appended content should go, if there is one. */ static nsContainerFrame* -AdjustAppendParentForAfterContent(nsPresContext* aPresContext, +AdjustAppendParentForAfterContent(nsFrameManager* aFrameManager, nsIContent* aContainer, nsContainerFrame* aParentFrame, + nsIContent* aChild, nsIFrame** aAfterFrame) { - // See if the parent has an :after pseudo-element. Check for the presence - // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive. - nsStyleContext* parentStyle = aParentFrame->StyleContext(); - if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle, + // If the parent frame has any pseudo-elements or aContainer is a + // display:contents node then we need to walk through the child + // frames to find the first one that is either a ::after frame for an + // ancestor of aChild or a frame that is for a node later in the + // document than aChild and return that in aAfterFrame. + if (aParentFrame->GetGenConPseudos() || + nsLayoutUtils::HasPseudoStyle(aContainer, aParentFrame->StyleContext(), nsCSSPseudoElements::ePseudo_after, - aPresContext)) { - // Ensure that the :after frame is on the principal child list. - aParentFrame->DrainSelfOverflowList(); + aParentFrame->PresContext()) || + aFrameManager->GetDisplayContentsStyleFor(aContainer)) { + nsIFrame* afterFrame = nullptr; + nsContainerFrame* parent = + static_cast(aParentFrame->LastContinuation()); + bool done = false; + while (!done && parent) { + // Ensure that all normal flow children are on the principal child list. + parent->DrainSelfOverflowList(); + + nsIFrame* child = parent->GetLastChild(nsIFrame::kPrincipalList); + if (child && child->IsPseudoFrame(aContainer) && + !child->IsGeneratedContentFrame()) { + // Drill down into non-generated pseudo frames of aContainer. + parent = nsLayoutUtils::LastContinuationWithChild(do_QueryFrame(child)); + continue; + } + + for (; child; child = child->GetPrevSibling()) { + nsIContent* c = child->GetContent(); + if (child->IsGeneratedContentFrame()) { + nsIContent* p = c->GetParent(); + if (c->Tag() == nsGkAtoms::mozgeneratedcontentafter) { + if (!nsContentUtils::ContentIsDescendantOf(aChild, p) && + p != aContainer && + nsContentUtils::PositionIsBefore(p, aChild)) { + // ::after generated content for content earlier in the doc and not + // for an ancestor. "p != aContainer" may seem redundant but it + // checks if the ::after belongs to the XBL insertion point we're + // inserting aChild into (in which case ContentIsDescendantOf is + // false even though p == aContainer). + // See layout/reftests/bugs/482592-1a.xhtml for an example of that. + done = true; + break; + } + } else if (nsContentUtils::PositionIsBefore(p, aChild)) { + // Non-::after generated content for content earlier in the doc. + done = true; + break; + } + } else if (nsContentUtils::PositionIsBefore(c, aChild)) { + // Content is before aChild. + done = true; + break; + } + afterFrame = child; + } - nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame); + parent = static_cast(parent->GetPrevContinuation()); + } if (afterFrame) { *aAfterFrame = afterFrame; return afterFrame->GetParent(); @@ -6143,15 +6287,19 @@ nsGkAtoms::menuFrame == parentType) { // if we haven't already, construct a style context to find the display type of aContent if (UNSET_DISPLAY == aDisplay) { - nsRefPtr styleContext; - nsIFrame* styleParent = aSibling->GetParentStyleContextFrame(); + nsIFrame* styleParent; + aSibling->GetParentStyleContext(&styleParent); + if (!styleParent) { + styleParent = aSibling->GetParent(); + } if (!styleParent) { NS_NOTREACHED("Shouldn't happen"); return false; } // XXXbz when this code is killed, the state argument to // ResolveStyleContext can be made non-optional. - styleContext = ResolveStyleContext(styleParent, aContent, nullptr); + nsRefPtr styleContext = + ResolveStyleContext(styleParent, aContent, nullptr); const nsStyleDisplay* display = styleContext->StyleDisplay(); aDisplay = display->mDisplay; } @@ -6211,10 +6359,33 @@ nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent, nsIContent* aTargetContent, uint8_t& aTargetContentDisplay, + nsContainerFrame* aParentFrame, bool aPrevSibling) { nsIFrame* sibling = aContent->GetPrimaryFrame(); - if (!sibling || sibling->GetContent() != aContent) { + if (!sibling && GetDisplayContentsStyleFor(aContent)) { + // A display:contents node - check if it has a ::before / ::after frame... + sibling = aPrevSibling ? + nsLayoutUtils::GetAfterFrameForContent(aParentFrame, aContent) : + nsLayoutUtils::GetBeforeFrameForContent(aParentFrame, aContent); + if (!sibling) { + // ... then recurse into children ... + const bool forward = !aPrevSibling; + FlattenedChildIterator iter(aContent, forward); + sibling = aPrevSibling ? + FindPreviousSibling(iter, aTargetContent, aTargetContentDisplay, aParentFrame) : + FindNextSibling(iter, aTargetContent, aTargetContentDisplay, aParentFrame); + } + if (!sibling) { + // ... then ::after / ::before on the opposite end. + sibling = aPrevSibling ? + nsLayoutUtils::GetBeforeFrameForContent(aParentFrame, aContent) : + nsLayoutUtils::GetAfterFrameForContent(aParentFrame, aContent); + } + if (!sibling) { + return nullptr; + } + } else if (!sibling || sibling->GetContent() != aContent) { // XXX the GetContent() != aContent check is needed due to bug 135040. // Remove it once that's fixed. return nullptr; @@ -6253,16 +6424,17 @@ nsIFrame* nsCSSFrameConstructor::FindPreviousSibling(FlattenedChildIterator aIter, - uint8_t& aTargetContentDisplay) + nsIContent* aTargetContent, + uint8_t& aTargetContentDisplay, + nsContainerFrame* aParentFrame) { - nsIContent* child = aIter.Get(); - // Note: not all content objects are associated with a frame (e.g., if it's - // `display: none') so keep looking until we find a previous frame + // `display: none') so keep looking until we find a previous frame. while (nsIContent* sibling = aIter.GetPreviousChild()) { + MOZ_ASSERT(sibling != aTargetContent); nsIFrame* prevSibling = - FindFrameForContentSibling(sibling, child, aTargetContentDisplay, true); - + FindFrameForContentSibling(sibling, aTargetContent, aTargetContentDisplay, + aParentFrame, true); if (prevSibling) { // Found a previous sibling, we're done! return prevSibling; @@ -6274,13 +6446,15 @@ nsIFrame* nsCSSFrameConstructor::FindNextSibling(FlattenedChildIterator aIter, - uint8_t& aTargetContentDisplay) + nsIContent* aTargetContent, + uint8_t& aTargetContentDisplay, + nsContainerFrame* aParentFrame) { - nsIContent* child = aIter.Get(); - while (nsIContent* sibling = aIter.GetNextChild()) { + MOZ_ASSERT(sibling != aTargetContent); nsIFrame* nextSibling = - FindFrameForContentSibling(sibling, child, aTargetContentDisplay, false); + FindFrameForContentSibling(sibling, aTargetContent, aTargetContentDisplay, + aParentFrame, false); if (nextSibling) { // We found a next sibling, we're done! @@ -6313,26 +6487,24 @@ } nsIFrame* -nsCSSFrameConstructor::GetInsertionPrevSibling(nsContainerFrame*& aParentFrame, - nsIContent* aContainer, +nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion, nsIContent* aChild, - bool* aIsAppend, - bool* aIsRangeInsertSafe, + bool* aIsAppend, + bool* aIsRangeInsertSafe, nsIContent* aStartSkipChild, nsIContent* aEndSkipChild) { + NS_PRECONDITION(aInsertion->mParentFrame, "Must have parent frame to start with"); + *aIsAppend = false; // Find the frame that precedes the insertion point. Walk backwards // from the parent frame to get the parent content, because if an // XBL insertion point is involved, we'll need to use _that_ to find // the preceding frame. - - NS_PRECONDITION(aParentFrame, "Must have parent frame to start with"); - nsIContent* container = aParentFrame->GetContent(); - - FlattenedChildIterator iter(container); - bool xblCase = iter.XBLInvolved() || container != aContainer; + FlattenedChildIterator iter(aInsertion->mContainer); + bool xblCase = iter.XBLInvolved() || + aInsertion->mParentFrame->GetContent() != aInsertion->mContainer; if (xblCase || !aChild->IsRootOfAnonymousSubtree()) { // The check for IsRootOfAnonymousSubtree() is because editor is // severely broken and calls us directly for native anonymous @@ -6352,47 +6524,66 @@ // Note that FindPreviousSibling is passed the iterator by value, so that // the later usage of the iterator starts from the same place. uint8_t childDisplay = UNSET_DISPLAY; - nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay); + nsIFrame* prevSibling = + FindPreviousSibling(iter, iter.Get(), childDisplay, aInsertion->mParentFrame); // Now, find the geometric parent so that we can handle // continuations properly. Use the prev sibling if we have it; // otherwise use the next sibling. if (prevSibling) { - aParentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); - } - else { + aInsertion->mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); + } else { // If there is no previous sibling, then find the frame that follows if (aEndSkipChild) { iter.Seek(aEndSkipChild); iter.GetPreviousChild(); } - nsIFrame* nextSibling = FindNextSibling(iter, childDisplay); + nsIFrame* nextSibling = + FindNextSibling(iter, iter.Get(), childDisplay, aInsertion->mParentFrame); + if (GetDisplayContentsStyleFor(aInsertion->mContainer)) { + if (!nextSibling) { + // Our siblings (if any) does not have a frame to guide us. + // The frame for aChild should be inserted whereever a frame for + // the container would be inserted. This is needed when inserting + // into nested display:contents nodes. + nsIContent* child = aInsertion->mContainer; + InsertionPoint fakeInsertion(aInsertion->mParentFrame, child->GetParent()); + nsIFrame* result = GetInsertionPrevSibling(&fakeInsertion, child, aIsAppend, + aIsRangeInsertSafe, nullptr, nullptr); + MOZ_ASSERT(aInsertion->mParentFrame == fakeInsertion.mParentFrame); + return result; + } - if (nextSibling) { - aParentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); + prevSibling = nextSibling->GetPrevSibling(); } - else { + + if (nextSibling) { + aInsertion->mParentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); + } else { // No previous or next sibling, so treat this like an appended frame. *aIsAppend = true; - if (IsFramePartOfIBSplit(aParentFrame)) { + if (IsFramePartOfIBSplit(aInsertion->mParentFrame)) { // Since we're appending, we'll walk to the last anonymous frame // that was created for the broken inline frame. But don't walk // to the trailing inline if it's empty; stop at the block. - aParentFrame = GetLastIBSplitSibling(aParentFrame, false); + aInsertion->mParentFrame = + GetLastIBSplitSibling(aInsertion->mParentFrame, false); } // Get continuation that parents the last child. This MUST be done // before the AdjustAppendParentForAfterContent call. - aParentFrame = nsLayoutUtils::LastContinuationWithChild(aParentFrame); + aInsertion->mParentFrame = + nsLayoutUtils::LastContinuationWithChild(aInsertion->mParentFrame); // Deal with fieldsets - aParentFrame = ::GetAdjustedParentFrame(aParentFrame, - aParentFrame->GetType(), - aChild); + aInsertion->mParentFrame = + ::GetAdjustedParentFrame(aInsertion->mParentFrame, + aInsertion->mParentFrame->GetType(), + aChild); nsIFrame* appendAfterFrame; - aParentFrame = - ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(), - container, aParentFrame, - &appendAfterFrame); - prevSibling = ::FindAppendPrevSibling(aParentFrame, appendAfterFrame); + aInsertion->mParentFrame = + ::AdjustAppendParentForAfterContent(this, aInsertion->mContainer, + aInsertion->mParentFrame, + aChild, &appendAfterFrame); + prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, appendAfterFrame); } } @@ -6400,6 +6591,40 @@ return prevSibling; } +nsContainerFrame* +nsCSSFrameConstructor::GetContentInsertionFrameFor(nsIContent* aContent) +{ + // Get the primary frame associated with the content + nsIFrame* frame = aContent->GetPrimaryFrame(); + + if (!frame) { + if (GetDisplayContentsStyleFor(aContent)) { + nsIContent* parent = aContent->GetParent(); + if (parent && parent == aContent->GetContainingShadow()) { + parent = parent->GetBindingParent(); + } + frame = parent ? GetContentInsertionFrameFor(parent) : nullptr; + } + if (!frame) { + return nullptr; + } + } else { + // If the content of the frame is not the desired content then this is not + // really a frame for the desired content. + // XXX This check is needed due to bug 135040. Remove it once that's fixed. + if (frame->GetContent() != aContent) { + return nullptr; + } + } + + nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame(); + + NS_ASSERTION(!insertionFrame || insertionFrame == frame || !frame->IsLeaf(), + "The insertion frame is the primary frame or the primary frame isn't a leaf"); + + return insertionFrame; +} + static bool IsSpecialFramesetChild(nsIContent* aContent) { @@ -6445,7 +6670,7 @@ void nsCSSFrameConstructor::AddTextItemIfNeeded(nsFrameConstructorState& aState, - nsContainerFrame* aParentFrame, + const InsertionPoint& aInsertion, nsIContent* aPossibleTextContent, FrameConstructionItemList& aItems) { @@ -6460,7 +6685,7 @@ NS_ASSERTION(!aPossibleTextContent->GetPrimaryFrame(), "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"); AddFrameConstructionItems(aState, aPossibleTextContent, false, - aParentFrame, aItems); + aInsertion, aItems); } void @@ -6537,6 +6762,10 @@ needsFrameBitSet = true; } #endif + // XXXmats no lazy frames for display:contents descendants yet (bug 979782). + if (GetDisplayContentsStyleFor(content)) { + return false; + } content->SetFlags(NODE_DESCENDANTS_NEED_FRAMES); content = content->GetFlattenedTreeParent(); } @@ -6659,8 +6888,8 @@ for (nsIContent* child = aStartChild; child != aEndChild; child = child->GetNextSibling()) { - if ((child->GetPrimaryFrame() || - GetUndisplayedContent(child)) + if ((child->GetPrimaryFrame() || GetUndisplayedContent(child) || + GetDisplayContentsStyleFor(child)) #ifdef MOZ_XUL // Except listboxes suck, so do NOT skip anything here if // we plan to notify a listbox. @@ -6678,7 +6907,7 @@ } } -nsContainerFrame* +nsCSSFrameConstructor::InsertionPoint nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aContainer, nsIContent* aStartChild, nsIContent* aEndChild, @@ -6687,13 +6916,13 @@ // See if we have an XBL insertion point. If so, then that's our // real parent frame; if not, then the frame hasn't been built yet // and we just bail. - bool multiple = false; - nsContainerFrame* insertionPoint = GetInsertionPoint(aContainer, nullptr, &multiple); - if (!insertionPoint && !multiple) - return nullptr; // Don't build the frames. + InsertionPoint insertionPoint = GetInsertionPoint(aContainer, nullptr); + if (!insertionPoint.mParentFrame && !insertionPoint.mMultiple) { + return insertionPoint; // Don't build the frames. + } bool hasInsertion = false; - if (!multiple) { + if (!insertionPoint.mMultiple) { // XXXbz XBL2/sXBL issue nsIDocument* document = aStartChild->GetComposedDoc(); // XXXbz how would |document| be null here? @@ -6702,12 +6931,12 @@ } } - if (multiple || hasInsertion) { + if (insertionPoint.mMultiple || hasInsertion) { // We have an insertion point. There are some additional tests we need to do // in order to ensure that an append is a safe operation. uint32_t childCount = 0; - if (!multiple) { + if (!insertionPoint.mMultiple) { // We may need to make multiple ContentInserted calls instead. A // reasonable heuristic to employ (in order to maintain good performance) // is to find out if the insertion point's content node contains any @@ -6720,19 +6949,19 @@ // multiple ContentInserted calls anyway. // XXXndeakin This test doesn't work in the new world. Or rather, it works, but // it's slow - childCount = insertionPoint->GetContent()->GetChildCount(); + childCount = insertionPoint.mParentFrame->GetContent()->GetChildCount(); } // If we have multiple insertion points or if we have an insertion point // and the operation is not a true append or if the insertion point already // has explicit children, then we must fall back. - if (multiple || aEndChild != nullptr || childCount > 0) { + if (insertionPoint.mMultiple || aEndChild != nullptr || childCount > 0) { // Now comes the fun part. For each inserted child, make a // ContentInserted call as if it had just gotten inserted and // let ContentInserted handle the mess. IssueSingleInsertNofications(aContainer, aStartChild, aEndChild, aAllowLazyConstruction); - return nullptr; + insertionPoint.mParentFrame = nullptr; } } @@ -6823,11 +7052,9 @@ return rv; } - // Get the frame associated with the content - nsContainerFrame* parentFrame = ::GetContentInsertionFrameFor(aContainer); - // See comment in ContentRangeInserted for why this is necessary. - if (!parentFrame && !aContainer->IsActiveChildrenElement()) { + if (!GetContentInsertionFrameFor(aContainer) && + !aContainer->IsActiveChildrenElement()) { return NS_OK; } @@ -6837,9 +7064,10 @@ } LAYOUT_PHASE_TEMP_EXIT(); - parentFrame = GetRangeInsertionPoint(aContainer, - aFirstNewContent, nullptr, - aAllowLazyConstruction); + InsertionPoint insertion = + GetRangeInsertionPoint(aContainer, aFirstNewContent, nullptr, + aAllowLazyConstruction); + nsContainerFrame*& parentFrame = insertion.mParentFrame; LAYOUT_PHASE_TEMP_REENTER(); if (!parentFrame) { return NS_OK; @@ -6898,9 +7126,8 @@ // Deal with possible :after generated content on the parent nsIFrame* parentAfterFrame; parentFrame = - ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(), - aContainer, parentFrame, - &parentAfterFrame); + ::AdjustAppendParentForAfterContent(this, insertion.mContainer, parentFrame, + aFirstNewContent, &parentAfterFrame); // Create some new frames nsFrameConstructorState state(mPresShell, @@ -6944,13 +7171,13 @@ // (text in an XBL binding is not suppressed) or generated content // (and bare text nodes are not generated). Native anonymous content // generated by frames never participates in inline layout. - AddTextItemIfNeeded(state, parentFrame, + AddTextItemIfNeeded(state, insertion, aFirstNewContent->GetPreviousSibling(), items); } for (nsIContent* child = aFirstNewContent; child; child = child->GetNextSibling()) { - AddFrameConstructionItems(state, child, false, parentFrame, items); + AddFrameConstructionItems(state, child, false, insertion, items); } nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, parentAfterFrame); @@ -7263,44 +7490,49 @@ return rv; } - nsContainerFrame* parentFrame = ::GetContentInsertionFrameFor(aContainer); - // The xbl:children element won't have a frame, but default content can have the children as - // a parent. While its uncommon to change the structure of the default content itself, a label, - // for example, can be reframed by having its value attribute set or removed. - if (!parentFrame && !aContainer->IsActiveChildrenElement()) { - return NS_OK; - } + // Put 'parentFrame' inside a scope so we don't confuse it with + // 'insertion.mParentFrame' later. + { + nsContainerFrame* parentFrame = GetContentInsertionFrameFor(aContainer); + // The xbl:children element won't have a frame, but default content can have the children as + // a parent. While its uncommon to change the structure of the default content itself, a label, + // for example, can be reframed by having its value attribute set or removed. + if (!parentFrame && !aContainer->IsActiveChildrenElement()) { + return NS_OK; + } - // Otherwise, we've got parent content. Find its frame. - NS_ASSERTION(!parentFrame || parentFrame->GetContent() == aContainer, "New XBL code is possibly wrong!"); + // Otherwise, we've got parent content. Find its frame. + NS_ASSERTION(!parentFrame || parentFrame->GetContent() == aContainer || + GetDisplayContentsStyleFor(aContainer), "New XBL code is possibly wrong!"); - if (aAllowLazyConstruction && - MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) { - return NS_OK; + if (aAllowLazyConstruction && + MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) { + return NS_OK; + } } + InsertionPoint insertion; if (isSingleInsert) { // See if we have an XBL insertion point. If so, then that's our // real parent frame; if not, then the frame hasn't been built yet // and we just bail. - parentFrame = GetInsertionPoint(aContainer, aStartChild); + insertion = GetInsertionPoint(aContainer, aStartChild); } else { // Get our insertion point. If we need to issue single ContentInserted's // GetRangeInsertionPoint will take care of that for us. LAYOUT_PHASE_TEMP_EXIT(); - parentFrame = GetRangeInsertionPoint(aContainer, aStartChild, aEndChild, - aAllowLazyConstruction); + insertion = GetRangeInsertionPoint(aContainer, aStartChild, aEndChild, + aAllowLazyConstruction); LAYOUT_PHASE_TEMP_REENTER(); } - if (!parentFrame) { + if (!insertion.mParentFrame) { return NS_OK; } bool isAppend, isRangeInsertSafe; - nsIFrame* prevSibling = - GetInsertionPrevSibling(parentFrame, aContainer, aStartChild, - &isAppend, &isRangeInsertSafe); + nsIFrame* prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, + &isAppend, &isRangeInsertSafe); // check if range insert is safe if (!isSingleInsert && !isRangeInsertSafe) { @@ -7312,11 +7544,11 @@ return NS_OK; } - nsIContent* container = parentFrame->GetContent(); + nsIContent* container = insertion.mParentFrame->GetContent(); - nsIAtom* frameType = parentFrame->GetType(); + nsIAtom* frameType = insertion.mParentFrame->GetType(); LAYOUT_PHASE_TEMP_EXIT(); - if (MaybeRecreateForFrameset(parentFrame, aStartChild, aEndChild)) { + if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild, aEndChild)) { LAYOUT_PHASE_TEMP_REENTER(); return NS_OK; } @@ -7326,7 +7558,7 @@ // fieldsets have multiple insertion points. NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame, "Unexpected parent"); - if (IsFrameForFieldSet(parentFrame, frameType) && + if (IsFrameForFieldSet(insertion.mParentFrame, frameType) && aStartChild->Tag() == nsGkAtoms::legend) { // Just reframe the parent, since figuring out whether this // should be the new legend and then handling it is too complex. @@ -7335,31 +7567,31 @@ // and if so, proceed. But we'd have to extend nsFieldSetFrame // to locate this legend in the inserted frames and extract it. LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false, + nsresult rv = RecreateFramesForContent(insertion.mParentFrame->GetContent(), false, REMOVE_FOR_RECONSTRUCTION, nullptr); LAYOUT_PHASE_TEMP_REENTER(); return rv; } // Don't construct kids of leaves - if (parentFrame->IsLeaf()) { + if (insertion.mParentFrame->IsLeaf()) { // Clear lazy bits so we don't try to construct again. ClearLazyBits(aStartChild, aEndChild); return NS_OK; } - if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) { + if (insertion.mParentFrame->IsFrameOfType(nsIFrame::eMathML)) { LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false, + nsresult rv = RecreateFramesForContent(insertion.mParentFrame->GetContent(), false, REMOVE_FOR_RECONSTRUCTION, nullptr); LAYOUT_PHASE_TEMP_REENTER(); return rv; } nsFrameConstructorState state(mPresShell, - GetAbsoluteContainingBlock(parentFrame, FIXED_POS), - GetAbsoluteContainingBlock(parentFrame, ABS_POS), - GetFloatContainingBlock(parentFrame), + GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS), + GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS), + GetFloatContainingBlock(insertion.mParentFrame), aFrameState); state.mTreeMatchContext.InitAncestors(aContainer ? aContainer->AsElement() : @@ -7378,9 +7610,9 @@ // containing block haveFirst* flags if the parent frame where // the insertion/append is occurring is an inline or block // container. For other types of containers this isn't relevant. - uint8_t parentDisplay = parentFrame->GetDisplay(); + uint8_t parentDisplay = insertion.mParentFrame->GetDisplay(); - // Examine the parentFrame where the insertion is taking + // Examine the insertion.mParentFrame where the insertion is taking // place. If it's a certain kind of container then some special // processing is done. if ((NS_STYLE_DISPLAY_BLOCK == parentDisplay) || @@ -7396,18 +7628,18 @@ } if (haveFirstLetterStyle) { - // If our current parentFrame is a Letter frame, use its parent as our + // If our current insertion.mParentFrame is a Letter frame, use its parent as our // new parent hint - if (parentFrame->GetType() == nsGkAtoms::letterFrame) { - // If parentFrame is out of flow, then we actually want the parent of + if (insertion.mParentFrame->GetType() == nsGkAtoms::letterFrame) { + // If insertion.mParentFrame is out of flow, then we actually want the parent of // the placeholder frame. - if (parentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { + if (insertion.mParentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { nsPlaceholderFrame* placeholderFrame = - GetPlaceholderFrameFor(parentFrame); + GetPlaceholderFrameFor(insertion.mParentFrame); NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?"); - parentFrame = placeholderFrame->GetParent(); + insertion.mParentFrame = placeholderFrame->GetParent(); } else { - parentFrame = parentFrame->GetParent(); + insertion.mParentFrame = insertion.mParentFrame->GetParent(); } } @@ -7418,8 +7650,7 @@ // Removing the letterframes messes around with the frame tree, removing // and creating frames. We need to reget our prevsibling, parent frame, // etc. - prevSibling = GetInsertionPrevSibling(parentFrame, aContainer, - aStartChild, &isAppend, + prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, &isAppend, &isRangeInsertSafe); // Need check whether a range insert is still safe. @@ -7435,22 +7666,22 @@ return NS_OK; } - container = parentFrame->GetContent(); - frameType = parentFrame->GetType(); + container = insertion.mParentFrame->GetContent(); + frameType = insertion.mParentFrame->GetType(); } } if (!prevSibling) { // We're inserting the new frames as the first child. See if the // parent has a :before pseudo-element - nsIFrame* firstChild = parentFrame->GetFirstPrincipalChild(); + nsIFrame* firstChild = insertion.mParentFrame->GetFirstPrincipalChild(); if (firstChild && nsLayoutUtils::IsGeneratedContentFor(container, firstChild, nsCSSPseudoElements::before)) { // Insert the new frames after the last continuation of the :before prevSibling = firstChild->GetTailContinuation(); - parentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); + insertion.mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); // Don't change isAppend here; we'll can call AppendFrames as needed, and // the change to our prevSibling doesn't affect that. } @@ -7467,19 +7698,19 @@ // it, because it might need a frame now. No need to do this if our // parent type is not block, though, since WipeContainingBlock // already handles that sitation. - AddTextItemIfNeeded(state, parentFrame, aStartChild->GetPreviousSibling(), + AddTextItemIfNeeded(state, insertion, aStartChild->GetPreviousSibling(), items); } if (isSingleInsert) { AddFrameConstructionItems(state, aStartChild, aStartChild->IsRootOfAnonymousSubtree(), - parentFrame, items); + insertion, items); } else { for (nsIContent* child = aStartChild; child != aEndChild; child = child->GetNextSibling()){ - AddFrameConstructionItems(state, child, false, parentFrame, items); + AddFrameConstructionItems(state, child, false, insertion, items); } } @@ -7489,7 +7720,7 @@ // it, because it might need a frame now. No need to do this if our // parent type is not block, though, since WipeContainingBlock // already handles that sitation. - AddTextItemIfNeeded(state, parentFrame, aEndChild, items); + AddTextItemIfNeeded(state, insertion, aEndChild, items); } // Perform special check for diddling around with the frames in @@ -7497,7 +7728,7 @@ // If we're appending before :after content, then we're not really // appending, so let WipeContainingBlock know that. LAYOUT_PHASE_TEMP_EXIT(); - if (WipeContainingBlock(state, containingBlock, parentFrame, items, + if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items, isAppend, prevSibling)) { LAYOUT_PHASE_TEMP_REENTER(); return NS_OK; @@ -7509,7 +7740,7 @@ // We make no attempt here to set flags to indicate whether the list // will be at the start or end of a block. It doesn't seem worthwhile. nsFrameItems frameItems, captionItems; - ConstructFramesFromItemList(state, items, parentFrame, frameItems); + ConstructFramesFromItemList(state, items, insertion.mParentFrame, frameItems); if (frameItems.NotEmpty()) { for (nsIContent* child = aStartChild; @@ -7560,15 +7791,14 @@ #endif isAppend = true; nsIFrame* appendAfterFrame; - parentFrame = - ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(), - container, + insertion.mParentFrame = + ::AdjustAppendParentForAfterContent(this, container, frameItems.FirstChild()->GetParent(), - &appendAfterFrame); - prevSibling = ::FindAppendPrevSibling(parentFrame, appendAfterFrame); + aStartChild, &appendAfterFrame); + prevSibling = ::FindAppendPrevSibling(insertion.mParentFrame, appendAfterFrame); } - if (haveFirstLineStyle && parentFrame == containingBlock) { + if (haveFirstLineStyle && insertion.mParentFrame == containingBlock) { // It's possible that the new frame goes into a first-line // frame. Look at it and see... if (isAppend) { @@ -7581,7 +7811,7 @@ // XXXbz this method is a no-op, so it's easy for the args being passed // here to make no sense without anyone noticing... If it ever stops // being a no-op, vet them carefully! - InsertFirstLineFrames(state, container, containingBlock, &parentFrame, + InsertFirstLineFrames(state, container, containingBlock, &insertion.mParentFrame, prevSibling, frameItems); } } @@ -7595,15 +7825,15 @@ // We need to determine where to put the caption items; start with the // the parent frame that has already been determined and get the insertion // prevsibling of the first caption item. - nsContainerFrame* captionParent = parentFrame; bool captionIsAppend; nsIFrame* captionPrevSibling = nullptr; // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here. bool ignored; + InsertionPoint captionInsertion(insertion.mParentFrame, insertion.mContainer); if (isSingleInsert) { captionPrevSibling = - GetInsertionPrevSibling(captionParent, aContainer, aStartChild, + GetInsertionPrevSibling(&captionInsertion, aStartChild, &captionIsAppend, &ignored); } else { nsIContent* firstCaption = captionItems.FirstChild()->GetContent(); @@ -7611,13 +7841,14 @@ // [aStartChild,aEndChild) when looking for a // prevsibling. captionPrevSibling = - GetInsertionPrevSibling(captionParent, aContainer, firstCaption, + GetInsertionPrevSibling(&captionInsertion, firstCaption, &captionIsAppend, &ignored, aStartChild, aEndChild); } nsContainerFrame* outerTable = nullptr; - if (GetCaptionAdjustedParent(captionParent, captionItems.FirstChild(), + if (GetCaptionAdjustedParent(captionInsertion.mParentFrame, + captionItems.FirstChild(), &outerTable)) { // If the parent is not an outer table frame we will try to add frames // to a named child list that the parent does not honour and the frames @@ -7645,9 +7876,9 @@ if (frameItems.NotEmpty()) { // Notify the parent frame if (isAppend) { - AppendFramesToParent(state, parentFrame, frameItems, prevSibling); + AppendFramesToParent(state, insertion.mParentFrame, frameItems, prevSibling); } else { - InsertFrames(parentFrame, kPrincipalList, prevSibling, frameItems); + InsertFrames(insertion.mParentFrame, kPrincipalList, prevSibling, frameItems); } } @@ -7658,9 +7889,9 @@ } #ifdef DEBUG - if (gReallyNoisyContentUpdates && parentFrame) { + if (gReallyNoisyContentUpdates && insertion.mParentFrame) { printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame model:\n"); - parentFrame->List(stdout, 0); + insertion.mParentFrame->List(stdout, 0); } #endif @@ -7708,18 +7939,53 @@ } #endif - nsPresContext *presContext = mPresShell->GetPresContext(); - nsresult rv = NS_OK; - - // Find the child frame that maps the content + nsresult rv = NS_OK; nsIFrame* childFrame = aChild->GetPrimaryFrame(); - if (!childFrame || childFrame->GetContent() != aChild) { // XXXbz the GetContent() != aChild check is needed due to bug 135040. // Remove it once that's fixed. ClearUndisplayedContentIn(aChild, aContainer); } + MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild), + "display:contents nodes shouldn't have a frame"); + if (!childFrame && GetDisplayContentsStyleFor(aChild)) { + nsIFrame* ancestorFrame = nullptr; + nsIContent* ancestor = aContainer; + for (; ancestor; ancestor = ancestor->GetParent()) { + ancestorFrame = ancestor->GetPrimaryFrame(); + if (ancestorFrame) { + break; + } + } + if (ancestorFrame) { + nsTArray* generated = ancestorFrame->GetGenConPseudos(); + if (generated) { + *aDidReconstruct = true; + LAYOUT_PHASE_TEMP_EXIT(); + // XXXmats Can we recreate frames only for the ::after/::before content? + // XXX Perhaps even only those that belong to the aChild sub-tree? + RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor); + LAYOUT_PHASE_TEMP_REENTER(); + return NS_OK; + } + } + + FlattenedChildIterator iter(aChild); + for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) { + if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) { + LAYOUT_PHASE_TEMP_EXIT(); + rv = ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct, aDestroyedFramesFor); + LAYOUT_PHASE_TEMP_REENTER(); + NS_ENSURE_SUCCESS(rv, rv); + if (aFlags != REMOVE_DESTROY_FRAMES && *aDidReconstruct) { + return rv; + } + } + } + ClearDisplayContentsIn(aChild, aContainer); + } + nsPresContext* presContext = mPresShell->GetPresContext(); #ifdef MOZ_XUL if (NotifyListBoxBody(presContext, aContainer, aChild, aOldNextSibling, mDocument, childFrame, CONTENT_REMOVED)) { @@ -8569,67 +8835,62 @@ return NS_OK; } -nsContainerFrame* -nsCSSFrameConstructor::GetInsertionPoint(nsIContent* aContainer, - nsIContent* aChildContent, - bool* aMultiple) +nsCSSFrameConstructor::InsertionPoint +nsCSSFrameConstructor::GetInsertionPoint(nsIContent* aContainer, + nsIContent* aChild) { - nsBindingManager *bindingManager = mDocument->BindingManager(); + nsBindingManager* bindingManager = mDocument->BindingManager(); nsIContent* insertionElement; - if (aChildContent) { + if (aChild) { // We've got an explicit insertion child. Check to see if it's // anonymous. - if (aChildContent->GetBindingParent() == aContainer) { + if (aChild->GetBindingParent() == aContainer) { // This child content is anonymous. Don't use the insertion // point, since that's only for the explicit kids. - return ::GetContentInsertionFrameFor(aContainer); + return InsertionPoint(GetContentInsertionFrameFor(aContainer), aContainer); } if (nsContentUtils::HasDistributedChildren(aContainer)) { // The container distributes nodes, use the frame of the flattened tree parent. // It may be the case that the node is distributed but not matched to any // insertion points, so there is no flattened parent. - nsIContent* flattenedParent = aChildContent->GetFlattenedTreeParent(); - return flattenedParent ? ::GetContentInsertionFrameFor(flattenedParent) : nullptr; + nsIContent* flattenedParent = aChild->GetFlattenedTreeParent(); + if (flattenedParent) { + return InsertionPoint(GetContentInsertionFrameFor(flattenedParent), + flattenedParent); + } + return InsertionPoint(); } - insertionElement = bindingManager->FindNestedInsertionPoint(aContainer, aChildContent); - } - else { + insertionElement = bindingManager->FindNestedInsertionPoint(aContainer, aChild); + } else { if (nsContentUtils::HasDistributedChildren(aContainer)) { // The container distributes nodes to shadow DOM insertion points. // Return with aMultiple set to true to induce callers to insert children // individually into the node's flattened tree parent. - *aMultiple = true; - return nullptr; + return InsertionPoint(nullptr, nullptr, true); } bool multiple; insertionElement = bindingManager->FindNestedSingleInsertionPoint(aContainer, &multiple); - if (multiple) { - if (aMultiple) { - *aMultiple = true; - } - return nullptr; + return InsertionPoint(nullptr, nullptr, true); } } if (!insertionElement) { insertionElement = aContainer; } + InsertionPoint insertion(GetContentInsertionFrameFor(insertionElement), + insertionElement); - nsContainerFrame* insertionPoint = - ::GetContentInsertionFrameFor(insertionElement); - - // fieldsets have multiple insertion points. Note that we might - // have to look at insertionElement here... - if (aMultiple && insertionElement->IsHTML(nsGkAtoms::fieldset)) { - *aMultiple = true; + // Fieldsets have multiple insertion points. + if (insertionElement->IsHTML(nsGkAtoms::fieldset)) { + insertion.mMultiple = true; } - return insertionPoint; + return insertion; } // Capture state for the frame tree rooted at the frame associated with the @@ -8658,36 +8919,46 @@ (aURI1 && aURI2 && aURI1->URIEquals(*aURI2)); } -nsresult +nsStyleContext* nsCSSFrameConstructor::MaybeRecreateFramesForElement(Element* aElement) { nsRefPtr oldContext = GetUndisplayedContent(aElement); + uint8_t oldDisplay = NS_STYLE_DISPLAY_NONE; if (!oldContext) { - return NS_OK; + oldContext = GetDisplayContentsStyleFor(aElement); + if (!oldContext) { + return nullptr; + } + oldDisplay = NS_STYLE_DISPLAY_CONTENTS; } // The parent has a frame, so try resolving a new context. nsRefPtr newContext = mPresShell->StyleSet()-> ResolveStyleFor(aElement, oldContext->GetParent()); - ChangeUndisplayedContent(aElement, newContext); + if (oldDisplay == NS_STYLE_DISPLAY_NONE) { + ChangeUndisplayedContent(aElement, newContext); + } else { + ChangeDisplayContents(aElement, newContext); + } + const nsStyleDisplay* disp = newContext->StyleDisplay(); - if (disp->mDisplay == NS_STYLE_DISPLAY_NONE) { + if (oldDisplay == disp->mDisplay) { // We can skip trying to recreate frames here, but only if our style // context does not have a binding URI that differs from our old one. // Otherwise, we should try to recreate, because we may want to apply the // new binding if (!disp->mBinding) { - return NS_OK; + return newContext; } const nsStyleDisplay* oldDisp = oldContext->PeekStyleDisplay(); if (oldDisp && EqualURIs(disp->mBinding, oldDisp->mBinding)) { - return NS_OK; + return newContext; } } - return RecreateFramesForContent(aElement, false, REMOVE_FOR_RECONSTRUCTION, - nullptr); + RecreateFramesForContent(aElement, false, REMOVE_FOR_RECONSTRUCTION, nullptr); + return nullptr; } static nsIFrame* @@ -9841,6 +10112,7 @@ NS_WARNING("ProcessChildren max depth exceeded"); } + InsertionPoint insertion(aFrame, nullptr); FlattenedChildIterator iter(aContent); for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { // Get the parent of the content and check if it is a XBL children element @@ -9848,10 +10120,13 @@ // FlattenedChildIterator will transitively iterate through // for default content). Push the children element as an ancestor here because // it does not have a frame and would not otherwise be pushed as an ancestor. + insertion.mContainer = aContent; nsIContent* parent = child->GetParent(); MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children."); TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext); if (parent != aContent && parent->IsElement()) { + insertion.mContainer = child->GetFlattenedTreeParent(); + MOZ_ASSERT(insertion.mContainer == GetInsertionPoint(parent, child).mContainer); if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { ancestorPusher.PushAncestorAndStyleScope(parent->AsElement()); } else { @@ -9865,7 +10140,7 @@ child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS); } if (addChildItems) { - AddFrameConstructionItems(aState, child, iter.XBLInvolved(), aFrame, + AddFrameConstructionItems(aState, child, iter.XBLInvolved(), insertion, itemsToConstruct); } else { ClearLazyBits(child, child->GetNextSibling()); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSFrameConstructor.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSFrameConstructor.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSFrameConstructor.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSFrameConstructor.h 2014-11-26 21:46:05.000000000 +0000 @@ -108,15 +108,48 @@ nsIContent* aEndChild, bool aAllowLazyConstruction); - // Checks if the children of aContainer in the range [aStartChild, aEndChild) - // can be inserted/appended to one insertion point together. If so, returns - // that insertion point. If not, returns null and issues single - // ContentInserted calls for each child. aEndChild = nullptr indicates that we - // are dealing with an append. - nsContainerFrame* GetRangeInsertionPoint(nsIContent* aContainer, - nsIContent* aStartChild, - nsIContent* aEndChild, - bool aAllowLazyConstruction); + /** + * Data that represents an insertion point for some child content. + */ + struct InsertionPoint + { + InsertionPoint() + : mParentFrame(nullptr), mContainer(nullptr), mMultiple(false) {} + InsertionPoint(nsContainerFrame* aParentFrame, nsIContent* aContainer, + bool aMultiple = false) + : mParentFrame(aParentFrame), mContainer(aContainer), + mMultiple(aMultiple) {} + /** + * The parent frame to use if the inserted children needs to create + * frame(s). May be null, which signals that we shouldn't try to + * create frames for the inserted children; either because there are + * no parent frame or because there are multiple insertion points and + * we will call IssueSingleInsertNofications for each child instead. + * mContainer should not be used when mParentFrame is null. + */ + nsContainerFrame* mParentFrame; + /** + * The flattened tree parent for the inserted children. + * It's undefined if mParentFrame is null. + */ + nsIContent* mContainer; + /** + * If true then there are multiple insertion points, which means consumers + * should insert children individually into the node's flattened tree parent. + */ + bool mMultiple; + }; + /** + * Checks if the children of aContainer in the range [aStartChild, aEndChild) + * can be inserted/appended to one insertion point together. If so, returns + * that insertion point. If not, returns with InsertionPoint.mFrame == nullptr + * and issues single ContentInserted calls for each child. + * aEndChild = nullptr indicates that we are dealing with an append. + */ + InsertionPoint GetRangeInsertionPoint(nsIContent* aContainer, + nsIContent* aStartChild, + nsIContent* aEndChild, + bool aAllowLazyConstruction); // Returns true if parent was recreated due to frameset child, false otherwise. bool MaybeRecreateForFrameset(nsIFrame* aParentFrame, @@ -266,10 +299,10 @@ // Copy over fixed frames from aParentFrame's prev-in-flow nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame); - // Get the XBL insertion point for a child - nsContainerFrame* GetInsertionPoint(nsIContent* aContainer, - nsIContent* aChildContent, - bool* aMultiple = nullptr); + /** + * Get the XBL insertion point for aChild in aContainer. + */ + InsertionPoint GetInsertionPoint(nsIContent* aContainer, nsIContent* aChild); nsresult CreateListBoxContent(nsPresContext* aPresContext, nsContainerFrame* aParentFrame, @@ -321,12 +354,21 @@ // aState can be null if not available; it's used as an optimization. // XXXbz IsValidSibling is the only caller that doesn't pass a state here! already_AddRefed - ResolveStyleContext(nsIFrame* aParentFrame, - nsIContent* aContent, + ResolveStyleContext(nsIFrame* aParentFrame, + nsIContent* aContainer, + nsIContent* aChild, + nsFrameConstructorState* aState); + already_AddRefed + ResolveStyleContext(nsIFrame* aParentFrame, + nsIContent* aChild, nsFrameConstructorState* aState); already_AddRefed - ResolveStyleContext(nsStyleContext* aParentStyleContext, - nsIContent* aContent, + ResolveStyleContext(const InsertionPoint& aInsertion, + nsIContent* aChild, + nsFrameConstructorState* aState); + already_AddRefed + ResolveStyleContext(nsStyleContext* aParentStyleContext, + nsIContent* aContent, nsFrameConstructorState* aState); // Add the frame construction items for the given aContent and aParentFrame @@ -337,9 +379,26 @@ void AddFrameConstructionItems(nsFrameConstructorState& aState, nsIContent* aContent, bool aSuppressWhiteSpaceOptimizations, - nsContainerFrame* aParentFrame, + const InsertionPoint& aInsertion, FrameConstructionItemList& aItems); + // Helper method for AddFrameConstructionItems etc. + // Unsets the need-frame/restyle bits on aContent. + // return true iff we should attempt to create frames for aContent. + bool ShouldCreateItemsForChild(nsFrameConstructorState& aState, + nsIContent* aContent, + nsContainerFrame* aParentFrame); + + // Helper method for AddFrameConstructionItems etc. + // Make sure ShouldCreateItemsForChild() returned true before calling this. + void DoAddFrameConstructionItems(nsFrameConstructorState& aState, + nsIContent* aContent, + nsStyleContext* aStyleContext, + bool aSuppressWhiteSpaceOptimizations, + nsContainerFrame* aParentFrame, + nsTArray* aAnonChildren, + FrameConstructionItemList& aItems); + // Construct the frames for the document element. This can return null if the // document element is display:none, or if the document element has a // not-yet-loaded XBL binding, or if it's an SVG element that's not . @@ -631,6 +690,10 @@ /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of an SVG text frame. */ #define FCDATA_IS_SVG_TEXT 0x80000 + /** + * display:contents + */ +#define FCDATA_IS_CONTENTS 0x100000 /* Structure representing information about how a frame should be constructed. */ @@ -1163,7 +1226,7 @@ // If aPossibleTextContent is a text node and doesn't have a frame, append a // frame construction item for it to aItems. void AddTextItemIfNeeded(nsFrameConstructorState& aState, - nsContainerFrame* aParentFrame, + const InsertionPoint& aInsertion, nsIContent* aPossibleTextContent, FrameConstructionItemList& aItems); @@ -1502,7 +1565,14 @@ PendingBinding* aPendingBinding, nsFrameItems& aFrameItems); - nsresult MaybeRecreateFramesForElement(Element* aElement); + /** + * ReResolve style for aElement then recreate frames if required. + * Do nothing for other types of style changes, except for undisplayed nodes + * (display:none/contents) which will have their style context updated in the + * frame manager undisplayed maps. + * @return null if frames were recreated, the new style context otherwise + */ + nsStyleContext* MaybeRecreateFramesForElement(Element* aElement); /** * Recreate frames for aContent. @@ -1772,29 +1842,64 @@ nsIFrame* aPrevSibling, nsFrameItems& aFrameItems); - // Find the right frame to use for aContent when looking for sibling - // frames for aTargetContent. If aPrevSibling is true, this - // will look for last continuations, etc, as necessary. This calls - // IsValidSibling as needed; if that returns false it returns null. - // - // @param aTargetContentDisplay the CSS display enum for aTargetContent if - // already known, UNSET_DISPLAY otherwise. It will be filled in if needed. + /** + * Find the right frame to use for aContent when looking for sibling + * frames for aTargetContent. If aPrevSibling is true, this + * will look for last continuations, etc, as necessary. This calls + * IsValidSibling as needed; if that returns false it returns null. + * + * @param aContent the content to search for frames + * @param aTargetContent the content we're finding a sibling frame for + * @param aTargetContentDisplay the CSS display enum for aTargetContent if + * already known, UNSET_DISPLAY otherwise. It will be filled in + * if needed. + * @param aParentFrame the nearest ancestor frame, used internally for + * finding ::after / ::before frames + * @param aPrevSibling true if we're searching in reverse DOM order + */ nsIFrame* FindFrameForContentSibling(nsIContent* aContent, nsIContent* aTargetContent, uint8_t& aTargetContentDisplay, + nsContainerFrame* aParentFrame, bool aPrevSibling); - // Find the ``rightmost'' frame for the content immediately preceding the one - // aIter points to, following continuations if necessary. aIter is passed by - // value on purpose, so as not to modify the caller's iterator. + /** + * Find the frame for the content immediately preceding the one aIter + * points to, following continuations if necessary. aIter is passed by + * value on purpose, so as not to modify the caller's iterator. + * + * @param aIter should be positioned such that aIter.GetPreviousChild() + * is the first content to search for frames + * @param aTargetContent the content we're finding a sibling frame for + * @param aTargetContentDisplay the CSS display enum for aTargetContent if + * already known, UNSET_DISPLAY otherwise. It will be filled in + * if needed. + * @param aParentFrame the nearest ancestor frame, used inernally for + * finding ::after / ::before frames + */ nsIFrame* FindPreviousSibling(mozilla::dom::FlattenedChildIterator aIter, - uint8_t& aTargetContentDisplay); + nsIContent* aTargetContent, + uint8_t& aTargetContentDisplay, + nsContainerFrame* aParentFrame); - // Find the frame for the content node immediately following the one aIter - // points to, following continuations if necessary. aIter is passed by value - // on purpose, so as not to modify the caller's iterator. + /** + * Find the frame for the content node immediately following the one aIter + * points to, following continuations if necessary. aIter is passed by value + * on purpose, so as not to modify the caller's iterator. + * + * @param aIter should be positioned such that aIter.GetNextChild() + * is the first content to search for frames + * @param aTargetContent the content we're finding a sibling frame for + * @param aTargetContentDisplay the CSS display enum for aTargetContent if + * already known, UNSET_DISPLAY otherwise. It will be filled in + * if needed. + * @param aParentFrame the nearest ancestor frame, used inernally for + * finding ::after / ::before frames + */ nsIFrame* FindNextSibling(mozilla::dom::FlattenedChildIterator aIter, - uint8_t& aTargetContentDisplay); + nsIContent* aTargetContent, + uint8_t& aTargetContentDisplay, + nsContainerFrame* aParentFrame); // Find the right previous sibling for an insertion. This also updates the // parent frame to point to the correct continuation of the parent frame to @@ -1809,14 +1914,19 @@ // including aEndSkipChild will be skipped over when looking for sibling // frames. Skipping a range can deal with XBL but not when there are multiple // insertion points. - nsIFrame* GetInsertionPrevSibling(nsContainerFrame*& aParentFrame, /* inout */ - nsIContent* aContainer, + nsIFrame* GetInsertionPrevSibling(InsertionPoint* aInsertion, // inout nsIContent* aChild, bool* aIsAppend, bool* aIsRangeInsertSafe, nsIContent* aStartSkipChild = nullptr, nsIContent *aEndSkipChild = nullptr); + /** + * Return the insertion frame of the primary frame of aContent, or its nearest + * ancestor that isn't display:contents. + */ + nsContainerFrame* GetContentInsertionFrameFor(nsIContent* aContent); + // see if aContent and aSibling are legitimate siblings due to restrictions // imposed by table columns // XXXbz this code is generally wrong, since the frame for aContent diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSRenderingBorders.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSRenderingBorders.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSRenderingBorders.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSRenderingBorders.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -1444,7 +1444,7 @@ strokeOptions.mDashOffset = 0.5f; DrawOptions drawOptions; drawOptions.mAntialiasMode = AntialiasMode::NONE; - mDrawTarget->StrokeRect(rect, color, strokeOptions); + mDrawTarget->StrokeRect(rect, color, strokeOptions, drawOptions); return; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSRendering.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSRendering.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsCSSRendering.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsCSSRendering.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -85,9 +85,9 @@ void Reset() { mBoundingBox.SetRect(0,0,0,0); - mContinuationPoint = mLineContinuationPoint = mUnbrokenWidth = 0; + mContinuationPoint = mLineContinuationPoint = mUnbrokenMeasure = 0; mFrame = mBlockFrame = nullptr; - mLeftBorderData.Reset(); + mPIStartBorderData.Reset(); } /** @@ -101,25 +101,31 @@ SetFrame(aFrame); - nscoord x; + nscoord pos; // an x coordinate if writing-mode is horizontal; + // y coordinate if vertical if (mBidiEnabled) { - x = mLineContinuationPoint; + pos = mLineContinuationPoint; // Scan continuations on the same line as aFrame and accumulate the widths // of frames that are to the left (if this is an LTR block) or right // (if it's RTL) of the current one. bool isRtlBlock = (mBlockFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL); - nscoord curOffset = aFrame->GetOffsetTo(mBlockFrame).x; + nscoord curOffset = mVertical ? aFrame->GetOffsetTo(mBlockFrame).y + : aFrame->GetOffsetTo(mBlockFrame).x; // If the continuation is fluid we know inlineFrame is not on the same line. // If it's not fluid, we need to test further to be sure. nsIFrame* inlineFrame = aFrame->GetPrevContinuation(); while (inlineFrame && !inlineFrame->GetNextInFlow() && AreOnSameLine(aFrame, inlineFrame)) { - nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x; - if(isRtlBlock == (frameXOffset >= curOffset)) { - x += inlineFrame->GetSize().width; + nscoord frameOffset = mVertical + ? inlineFrame->GetOffsetTo(mBlockFrame).y + : inlineFrame->GetOffsetTo(mBlockFrame).x; + if (isRtlBlock == (frameOffset >= curOffset)) { + pos += mVertical + ? inlineFrame->GetSize().height + : inlineFrame->GetSize().width; } inlineFrame = inlineFrame->GetPrevContinuation(); } @@ -127,59 +133,82 @@ inlineFrame = aFrame->GetNextContinuation(); while (inlineFrame && !inlineFrame->GetPrevInFlow() && AreOnSameLine(aFrame, inlineFrame)) { - nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x; - if(isRtlBlock == (frameXOffset >= curOffset)) { - x += inlineFrame->GetSize().width; + nscoord frameOffset = mVertical + ? inlineFrame->GetOffsetTo(mBlockFrame).y + : inlineFrame->GetOffsetTo(mBlockFrame).x; + if (isRtlBlock == (frameOffset >= curOffset)) { + pos += mVertical + ? inlineFrame->GetSize().height + : inlineFrame->GetSize().width; } inlineFrame = inlineFrame->GetNextContinuation(); } if (isRtlBlock) { // aFrame itself is also to the right of its left edge, so add its width. - x += aFrame->GetSize().width; - // x is now the distance from the left edge of aFrame to the right edge + pos += mVertical ? aFrame->GetSize().height : aFrame->GetSize().width; + // pos is now the distance from the left [top] edge of aFrame to the right [bottom] edge // of the unbroken content. Change it to indicate the distance from the - // left edge of the unbroken content to the left edge of aFrame. - x = mUnbrokenWidth - x; + // left [top] edge of the unbroken content to the left [top] edge of aFrame. + pos = mUnbrokenMeasure - pos; } } else { - x = mContinuationPoint; + pos = mContinuationPoint; } // Assume background-origin: border and return a rect with offsets // relative to (0,0). If we have a different background-origin, // then our rect should be deflated appropriately by our caller. - return nsRect(-x, 0, mUnbrokenWidth, mFrame->GetSize().height); + return mVertical + ? nsRect(0, -pos, mFrame->GetSize().width, mUnbrokenMeasure) + : nsRect(-pos, 0, mUnbrokenMeasure, mFrame->GetSize().height); } /** * Return a continuous rect for (an inline) aFrame relative to the - * continuation that should draw the left-border. This is used when painting + * continuation that should draw the left[top]-border. This is used when painting * borders and clipping backgrounds. This may NOT be the same continuous rect - * as for drawing backgrounds; the continuation with the left-border might be + * as for drawing backgrounds; the continuation with the left[top]-border might be * somewhere in the middle of that rect (e.g. BIDI), in those cases we need - * the reverse background order starting at the left-border continuation. + * the reverse background order starting at the left[top]-border continuation. */ nsRect GetBorderContinuousRect(nsIFrame* aFrame, nsRect aBorderArea) { // Calling GetContinuousRect(aFrame) here may lead to Reset/Init which - // resets our mLeftBorderData so we save it ... - LeftBorderData saved(mLeftBorderData); + // resets our mPIStartBorderData so we save it ... + PhysicalInlineStartBorderData saved(mPIStartBorderData); nsRect joinedBorderArea = GetContinuousRect(aFrame); - if (!saved.mIsValid || saved.mFrame != mLeftBorderData.mFrame) { - if (aFrame == mLeftBorderData.mFrame) { - mLeftBorderData.SetX(joinedBorderArea.x); - } else if (mLeftBorderData.mFrame) { - mLeftBorderData.SetX(GetContinuousRect(mLeftBorderData.mFrame).x); + if (!saved.mIsValid || saved.mFrame != mPIStartBorderData.mFrame) { + if (aFrame == mPIStartBorderData.mFrame) { + if (mVertical) { + mPIStartBorderData.SetCoord(joinedBorderArea.y); + } else { + mPIStartBorderData.SetCoord(joinedBorderArea.x); + } + } else if (mPIStartBorderData.mFrame) { + if (mVertical) { + mPIStartBorderData.SetCoord(GetContinuousRect(mPIStartBorderData.mFrame).y); + } else { + mPIStartBorderData.SetCoord(GetContinuousRect(mPIStartBorderData.mFrame).x); + } } } else { // ... and restore it when possible. - mLeftBorderData.mX = saved.mX; + mPIStartBorderData.mCoord = saved.mCoord; } - if (joinedBorderArea.x > mLeftBorderData.mX) { - joinedBorderArea.x = - -(mUnbrokenWidth + joinedBorderArea.x - aBorderArea.width); + if (mVertical) { + if (joinedBorderArea.y > mPIStartBorderData.mCoord) { + joinedBorderArea.y = + -(mUnbrokenMeasure + joinedBorderArea.y - aBorderArea.height); + } else { + joinedBorderArea.y -= mPIStartBorderData.mCoord; + } } else { - joinedBorderArea.x -= mLeftBorderData.mX; + if (joinedBorderArea.x > mPIStartBorderData.mCoord) { + joinedBorderArea.x = + -(mUnbrokenMeasure + joinedBorderArea.x - aBorderArea.width); + } else { + joinedBorderArea.x -= mPIStartBorderData.mCoord; + } } return joinedBorderArea; } @@ -201,22 +230,27 @@ } protected: - struct LeftBorderData { + // This is a coordinate on the inline axis, but is not a true logical inline- + // coord because it is always measured from left to right (if horizontal) or + // from top to bottom (if vertical), ignoring any bidi RTL directionality. + // We'll call this "physical inline start", or PIStart for short. + struct PhysicalInlineStartBorderData { nsIFrame* mFrame; // the continuation that may have a left-border - nscoord mX; // cached GetContinuousRect(mFrame).x - bool mIsValid; // true if mX is valid + nscoord mCoord; // cached GetContinuousRect(mFrame).x or .y + bool mIsValid; // true if mCoord is valid void Reset() { mFrame = nullptr; mIsValid = false; } - void SetX(nscoord aX) { mX = aX; mIsValid = true; } + void SetCoord(nscoord aCoord) { mCoord = aCoord; mIsValid = true; } }; nsIFrame* mFrame; nsBlockFrame* mBlockFrame; nsRect mBoundingBox; nscoord mContinuationPoint; - nscoord mUnbrokenWidth; + nscoord mUnbrokenMeasure; nscoord mLineContinuationPoint; - LeftBorderData mLeftBorderData; + PhysicalInlineStartBorderData mPIStartBorderData; bool mBidiEnabled; + bool mVertical; void SetFrame(nsIFrame* aFrame) { @@ -239,7 +273,8 @@ // Get our last frame's size and add its width to our continuation // point before we cache the new frame. - mContinuationPoint += mFrame->GetSize().width; + mContinuationPoint += mVertical ? mFrame->GetSize().height + : mFrame->GetSize().width; // If this a new line, update mLineContinuationPoint. if (mBidiEnabled && @@ -289,7 +324,7 @@ void Init(nsIFrame* aFrame) { - mLeftBorderData.Reset(); + mPIStartBorderData.Reset(); mBidiEnabled = aFrame->PresContext()->BidiEnabled(); if (mBidiEnabled) { // Find the containing block frame @@ -303,20 +338,23 @@ NS_ASSERTION(mBlockFrame, "Cannot find containing block."); } + mVertical = aFrame->GetWritingMode().IsVertical(); + // Start with the previous flow frame as our continuation point // is the total of the widths of the previous frames. nsIFrame* inlineFrame = GetPrevContinuation(aFrame); while (inlineFrame) { - if (!mLeftBorderData.mFrame && - !inlineFrame->GetSkipSides().Left()) { - mLeftBorderData.mFrame = inlineFrame; + if (!mPIStartBorderData.mFrame && + !(mVertical ? inlineFrame->GetSkipSides().Top() + : inlineFrame->GetSkipSides().Left())) { + mPIStartBorderData.mFrame = inlineFrame; } nsRect rect = inlineFrame->GetRect(); - mContinuationPoint += rect.width; + mContinuationPoint += mVertical ? rect.height : rect.width; if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) { - mLineContinuationPoint += rect.width; + mLineContinuationPoint += mVertical ? rect.height : rect.width; } - mUnbrokenWidth += rect.width; + mUnbrokenMeasure += mVertical ? rect.height : rect.width; mBoundingBox.UnionRect(mBoundingBox, rect); inlineFrame = GetPrevContinuation(inlineFrame); } @@ -325,12 +363,13 @@ // unbroken width. inlineFrame = aFrame; while (inlineFrame) { - if (!mLeftBorderData.mFrame && - !inlineFrame->GetSkipSides().Left()) { - mLeftBorderData.mFrame = inlineFrame; + if (!mPIStartBorderData.mFrame && + !(mVertical ? inlineFrame->GetSkipSides().Top() + : inlineFrame->GetSkipSides().Left())) { + mPIStartBorderData.mFrame = inlineFrame; } nsRect rect = inlineFrame->GetRect(); - mUnbrokenWidth += rect.width; + mUnbrokenMeasure += mVertical ? rect.height : rect.width; mBoundingBox.UnionRect(mBoundingBox, rect); inlineFrame = GetNextContinuation(inlineFrame); } @@ -632,6 +671,8 @@ nsStyleContext* aStyleContext, Sides aSkipSides) { + DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget(); + PrintAsStringNewline("++ PaintBorder"); // Check to see if we have an appearance defined. If so, we let the theme @@ -692,7 +733,7 @@ aRenderingContext.ThebesContext()-> Clip(NSRectToSnappedRect(aBorderArea, aForFrame->PresContext()->AppUnitsPerDevPixel(), - *aRenderingContext.GetDrawTarget())); + aDrawTarget)); } } else { MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea), @@ -731,14 +772,11 @@ #if 0 // this will draw a transparent red backround underneath the border area - ctx->Save(); - ctx->Rectangle(ThebesRect(joinedBorderAreaPx)); - ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5)); - ctx->Fill(); - ctx->Restore(); + ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 0.5f))); + aDrawTarget.FillRect(joinedBorderAreaPx, color); #endif - nsCSSBorderRenderer br(ctx->GetDrawTarget(), + nsCSSBorderRenderer br(&aDrawTarget, joinedBorderAreaPx, borderStyles, borderWidths, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsDisplayList.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsDisplayList.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsDisplayList.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsDisplayList.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -62,6 +62,7 @@ #include "UnitTransforms.h" #include "LayersLogging.h" #include "FrameLayerBuilder.h" +#include "RestyleManager.h" #include "nsCaret.h" #include "nsISelection.h" @@ -440,6 +441,15 @@ aLayer->ClearAnimations(); } + // Update the animation generation on the layer. We need to do this before + // any early returns since even if we don't add any animations to the + // layer, we still need to mark it as up-to-date with regards to animations. + // Otherwise, in RestyleManager we'll notice the discrepancy between the + // animation generation numbers and update the layer indefinitely. + uint64_t animationGeneration = + RestyleManager::GetMaxAnimationGenerationForFrame(aFrame); + aLayer->SetAnimationGeneration(animationGeneration); + nsIContent* content = aFrame->GetContent(); if (!content) { return; @@ -507,13 +517,11 @@ if (transitions) { AddAnimationsForProperty(aFrame, aProperty, transitions->mPlayers, aLayer, data, pending); - aLayer->SetAnimationGeneration(transitions->mAnimationGeneration); } if (animations) { AddAnimationsForProperty(aFrame, aProperty, animations->mPlayers, aLayer, data, pending); - aLayer->SetAnimationGeneration(animations->mAnimationGeneration); } } @@ -525,6 +533,7 @@ mCurrentTableItem(nullptr), mCurrentFrame(aReferenceFrame), mCurrentReferenceFrame(aReferenceFrame), + mCurrentAnimatedGeometryRoot(aReferenceFrame), mWillChangeBudgetCalculated(false), mDirtyRect(-1,-1,-1,-1), mGlassDisplayItem(nullptr), @@ -715,6 +724,11 @@ if (lastSmoothScrollOrigin) { metrics.SetSmoothScrollOffsetUpdated(scrollableFrame->CurrentScrollGeneration()); } + + nsSize lineScrollAmount = scrollableFrame->GetLineScrollAmount(); + LayoutDeviceIntSize lineScrollAmountInDevPixels = + LayoutDeviceIntSize::FromAppUnitsRounded(lineScrollAmount, presContext->AppUnitsPerDevPixel()); + metrics.SetLineScrollAmount(lineScrollAmountInDevPixels); } metrics.SetScrollId(scrollId); @@ -1068,6 +1082,104 @@ return mReferenceFrame; } +// Sticky frames are active if their nearest scrollable frame is also active. +static bool +IsStickyFrameActive(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsIFrame* aParent) +{ + MOZ_ASSERT(aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY); + + // Find the nearest scrollframe. + nsIFrame* cursor = aFrame; + nsIFrame* parent = aParent; + while (parent->GetType() != nsGkAtoms::scrollFrame) { + cursor = parent; + if ((parent = nsLayoutUtils::GetCrossDocParentFrame(cursor)) == nullptr) { + return false; + } + } + + nsIScrollableFrame* sf = do_QueryFrame(parent); + return sf->IsScrollingActive(aBuilder) && sf->GetScrolledFrame() == cursor; +} + +bool +nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent) +{ + if (nsLayoutUtils::IsPopup(aFrame)) + return true; + if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(aFrame)) + return true; + if (!aFrame->GetParent() && + nsLayoutUtils::ViewportHasDisplayPort(aFrame->PresContext())) { + // Viewport frames in a display port need to be animated geometry roots + // for background-attachment:fixed elements. + return true; + } + + nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); + if (!parent) + return true; + + nsIAtom* parentType = parent->GetType(); + // Treat the slider thumb as being as an active scrolled root when it wants + // its own layer so that it can move without repainting. + if (parentType == nsGkAtoms::sliderFrame && nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) { + return true; + } + + if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY && + IsStickyFrameActive(this, aFrame, parent)) + { + return true; + } + + if (parentType == nsGkAtoms::scrollFrame) { + nsIScrollableFrame* sf = do_QueryFrame(parent); + if (sf->IsScrollingActive(this) && sf->GetScrolledFrame() == aFrame) { + return true; + } + } + + // Fixed-pos frames are parented by the viewport frame, which has no parent. + if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame)) { + return true; + } + + if (aParent) { + *aParent = parent; + } + return false; +} + +static nsIFrame* +ComputeAnimatedGeometryRootFor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + const nsIFrame* aStopAtAncestor = nullptr) +{ + nsIFrame* cursor = aFrame; + while (cursor != aStopAtAncestor) { + nsIFrame* next; + if (aBuilder->IsAnimatedGeometryRoot(cursor, &next)) + return cursor; + cursor = next; + } + return cursor; +} + +nsIFrame* +nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsIFrame* aFrame, const nsIFrame* aStopAtAncestor) +{ + if (aFrame == mCurrentFrame) { + return mCurrentAnimatedGeometryRoot; + } + return ComputeAnimatedGeometryRootFor(this, aFrame, aStopAtAncestor); +} + +void +nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot() +{ + mCurrentAnimatedGeometryRoot = ComputeAnimatedGeometryRootFor(this, const_cast(mCurrentFrame)); +} + void nsDisplayListBuilder::AdjustWindowDraggingRegion(nsIFrame* aFrame) { @@ -1837,11 +1949,13 @@ #ifdef MOZ_DUMP_PAINTING void -nsDisplaySolidColor::WriteDebugInfo(nsACString& aTo) +nsDisplaySolidColor::WriteDebugInfo(std::stringstream& aStream) { - aTo += nsPrintfCString(" (rgba %d,%d,%d,%d)", - NS_GET_R(mColor), NS_GET_G(mColor), - NS_GET_B(mColor), NS_GET_A(mColor)); + aStream << " (rgba " + << (int)NS_GET_R(mColor) << "," + << (int)NS_GET_G(mColor) << "," + << (int)NS_GET_B(mColor) << "," + << (int)NS_GET_A(mColor) << ")"; } #endif @@ -2551,9 +2665,9 @@ #ifdef MOZ_DUMP_PAINTING void -nsDisplayThemedBackground::WriteDebugInfo(nsACString& aTo) +nsDisplayThemedBackground::WriteDebugInfo(std::stringstream& aStream) { - aTo += nsPrintfCString(" (themed, appearance:%d)", mAppearance); + aStream << " (themed, appearance:" << (int)mAppearance << ")"; } #endif @@ -2699,20 +2813,19 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { + DrawTarget& aDrawTarget = *aCtx->GetDrawTarget(); + if (mColor == NS_RGBA(0, 0, 0, 0)) { return; } - gfxContext* ctx = aCtx->ThebesContext(); nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize()); - gfxRect bounds = - nsLayoutUtils::RectToGfxRect(borderBox, mFrame->PresContext()->AppUnitsPerDevPixel()); - - ctx->SetColor(mColor); - ctx->NewPath(); - ctx->Rectangle(bounds, true); - ctx->Fill(); + Rect rect = NSRectToSnappedRect(borderBox, + mFrame->PresContext()->AppUnitsPerDevPixel(), + aDrawTarget); + ColorPattern color(ToDeviceColor(mColor)); + aDrawTarget.FillRect(rect, color); } nsRegion @@ -2757,11 +2870,10 @@ #ifdef MOZ_DUMP_PAINTING void -nsDisplayBackgroundColor::WriteDebugInfo(nsACString& aTo) +nsDisplayBackgroundColor::WriteDebugInfo(std::stringstream& aStream) { - aTo += nsPrintfCString(" (rgba %f,%f,%f,%f)", - mColor.r, mColor.g, - mColor.b, mColor.a); + aStream << " (rgba " << mColor.r << "," << mColor.g << "," + << mColor.b << "," << mColor.a << ")"; } #endif @@ -2846,6 +2958,9 @@ if (pointerEvents == NS_STYLE_POINTER_EVENTS_NONE) { return; } + if (!aFrame->StyleVisibility()->IsVisible()) { + return; + } // XXX handle other pointerEvents values for SVG // XXX Do something clever here for the common case where the border box // is obviously entirely inside mHitRegion. @@ -2870,6 +2985,28 @@ } } +void +nsDisplayLayerEventRegions::AddInactiveScrollPort(const nsRect& aRect) +{ + mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aRect); +} + +#ifdef MOZ_DUMP_PAINTING +void +nsDisplayLayerEventRegions::WriteDebugInfo(std::stringstream& aStream) +{ + if (!mHitRegion.IsEmpty()) { + AppendToString(aStream, mHitRegion, " (hitRegion ", ")"); + } + if (!mMaybeHitRegion.IsEmpty()) { + AppendToString(aStream, mMaybeHitRegion, " (maybeHitRegion ", ")"); + } + if (!mDispatchToContentHitRegion.IsEmpty()) { + AppendToString(aStream, mDispatchToContentHitRegion, " (dispatchToContentRegion ", ")"); + } +} +#endif + nsDisplayCaret::nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame) : nsDisplayItem(aBuilder, aCaretFrame) @@ -3561,9 +3698,9 @@ #ifdef MOZ_DUMP_PAINTING void -nsDisplayOpacity::WriteDebugInfo(nsACString& aTo) +nsDisplayOpacity::WriteDebugInfo(std::stringstream& aStream) { - aTo += nsPrintfCString(" (opacity %f)", mOpacity); + aStream << " (opacity " << mOpacity << ")"; } #endif @@ -3783,7 +3920,9 @@ nsPresContext* presContext = mFrame->PresContext(); nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame(); bool isRootContentDocument = presContext->IsRootContentDocument(); - ContainerLayerParameters params = aContainerParameters; + nsIPresShell* presShell = presContext->PresShell(); + ContainerLayerParameters params(presShell->GetXResolution(), + presShell->GetYResolution(), nsIntPoint(), aContainerParameters); if ((mFlags & GENERATE_SCROLLABLE_LAYER) && rootScrollFrame->GetContent() && nsLayoutUtils::GetCriticalDisplayPort(rootScrollFrame->GetContent(), nullptr)) { @@ -4324,10 +4463,10 @@ #ifdef MOZ_DUMP_PAINTING void -nsDisplayScrollLayer::WriteDebugInfo(nsACString& aTo) +nsDisplayScrollLayer::WriteDebugInfo(std::stringstream& aStream) { - aTo += nsPrintfCString(" (scrollframe %p scrolledframe %p)", - mScrollFrame, mScrolledFrame); + aStream << " (scrollframe " << mScrollFrame + << " scrolledFrame " << mScrolledFrame << ")"; } #endif @@ -4698,11 +4837,18 @@ //TODO: Should this be using our bounds or the parent's bounds? // How do we handle aBoundsOverride in the latter case? - nsIFrame* parent = aFrame->GetParentStyleContextFrame(); - if (!parent) { + nsIFrame* parent; + nsStyleContext* psc = aFrame->GetParentStyleContext(&parent); + if (!psc) { return Point3D(); } - const nsStyleDisplay* display = parent->StyleDisplay(); + if (!parent) { + parent = aFrame->GetParent(); + if (!parent) { + return Point3D(); + } + } + const nsStyleDisplay* display = psc->StyleDisplay(); nsRect boundingRect = nsDisplayTransform::GetFrameBoundsForTransform(parent); /* Allows us to access named variables by index. */ @@ -5505,11 +5651,9 @@ #ifdef MOZ_DUMP_PAINTING void -nsDisplayTransform::WriteDebugInfo(nsACString& aTo) +nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream) { - std::stringstream ss; - AppendToString(ss, GetTransform()); - aTo += ss.str().c_str(); + AppendToString(aStream, GetTransform()); } #endif @@ -5528,6 +5672,30 @@ } #endif +nsDisplayVR::nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList, mozilla::gfx::VRHMDInfo* aHMD) + : nsDisplayOwnLayer(aBuilder, aFrame, aList) + , mHMD(aHMD) +{ +} + +already_AddRefed +nsDisplayVR::BuildLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) +{ + ContainerLayerParameters newContainerParameters = aContainerParameters; + uint32_t flags = FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS; + nsRefPtr container = aManager->GetLayerBuilder()-> + BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList, + newContainerParameters, nullptr, flags); + + container->SetVRHMDInfo(mHMD); + container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(), + /*the value is irrelevant*/nullptr); + + return container.forget(); +} nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsDisplayList.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsDisplayList.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsDisplayList.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsDisplayList.h 2014-11-26 21:46:05.000000000 +0000 @@ -28,6 +28,7 @@ #include "FrameMetrics.h" #include "mozilla/UniquePtr.h" #include "mozilla/gfx/UserData.h" +#include "gfxVR.h" #include #include "nsTHashtable.h" @@ -209,7 +210,19 @@ */ const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame, nsPoint* aOffset = nullptr); - + + /** + * Returns whether a frame acts as an animated geometry root, optionally + * returning the next ancestor to check. + */ + bool IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent = nullptr); + + /** + * Returns the nearest ancestor frame to aFrame that is considered to have + * (or will have) animated geometry. This can return aFrame. + */ + nsIFrame* FindAnimatedGeometryRootFor(nsIFrame* aFrame, const nsIFrame* aStopAtAncestor = nullptr); + /** * @return the root of the display list's frame (sub)tree, whose origin * establishes the coordinate system for the display list @@ -311,6 +324,10 @@ const nsIFrame* GetCurrentFrame() { return mCurrentFrame; } const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; } const nsPoint& GetCurrentFrameOffsetToReferenceFrame() { return mCurrentOffsetToReferenceFrame; } + const nsIFrame* GetCurrentAnimatedGeometryRoot() { + return mCurrentAnimatedGeometryRoot; + } + void RecomputeCurrentAnimatedGeometryRoot(); /** * Returns true if merging and flattening of display lists should be @@ -539,6 +556,7 @@ : mBuilder(aBuilder), mPrevFrame(aBuilder->mCurrentFrame), mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame), + mPrevAnimatedGeometryRoot(mBuilder->mCurrentAnimatedGeometryRoot), mPrevLayerEventRegions(aBuilder->mLayerEventRegions), mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame), mPrevDirtyRect(aBuilder->mDirtyRect), @@ -555,6 +573,16 @@ aBuilder->FindReferenceFrameFor(aForChild, &aBuilder->mCurrentOffsetToReferenceFrame); } + if (aBuilder->mCurrentFrame == aForChild->GetParent()) { + if (aBuilder->IsAnimatedGeometryRoot(aForChild)) { + aBuilder->mCurrentAnimatedGeometryRoot = aForChild; + } + } else { + // Stop at the previous animated geometry root to help cases that + // aren't immediate descendents. + aBuilder->mCurrentAnimatedGeometryRoot = + aBuilder->FindAnimatedGeometryRootFor(aForChild, aBuilder->mCurrentAnimatedGeometryRoot); + } aBuilder->mCurrentFrame = aForChild; aBuilder->mDirtyRect = aDirtyRect; aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot; @@ -566,6 +594,11 @@ mBuilder->mCurrentReferenceFrame = aFrame; mBuilder->mCurrentOffsetToReferenceFrame = aOffset; } + // Return the previous frame's animated geometry root, whether or not the + // current frame is an immediate descendant. + const nsIFrame* GetPrevAnimatedGeometryRoot() const { + return mPrevAnimatedGeometryRoot; + } ~AutoBuildingDisplayList() { mBuilder->mCurrentFrame = mPrevFrame; mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame; @@ -574,11 +607,13 @@ mBuilder->mDirtyRect = mPrevDirtyRect; mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext; mBuilder->mAncestorHasTouchEventHandler = mPrevAncestorHasTouchEventHandler; + mBuilder->mCurrentAnimatedGeometryRoot = mPrevAnimatedGeometryRoot; } private: nsDisplayListBuilder* mBuilder; const nsIFrame* mPrevFrame; const nsIFrame* mPrevReferenceFrame; + nsIFrame* mPrevAnimatedGeometryRoot; nsDisplayLayerEventRegions* mPrevLayerEventRegions; nsPoint mPrevOffset; nsRect mPrevDirtyRect; @@ -795,6 +830,8 @@ const nsIFrame* mCurrentReferenceFrame; // The offset from mCurrentFrame to mCurrentReferenceFrame. nsPoint mCurrentOffsetToReferenceFrame; + // The animated geometry root for mCurrentFrame. + nsIFrame* mCurrentAnimatedGeometryRoot; // will-change budget tracker nsDataHashtable, DocumentWillChangeBudget> mWillChangeBudget; @@ -1308,7 +1345,7 @@ */ virtual const char* Name() = 0; - virtual void WriteDebugInfo(nsACString& aTo) {} + virtual void WriteDebugInfo(std::stringstream& aStream) {} #endif nsDisplayItem* GetAbove() { return mAbove; } @@ -2128,7 +2165,7 @@ } #ifdef MOZ_DUMP_PAINTING - virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; #endif NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR) @@ -2289,7 +2326,7 @@ nsRegion* aInvalidRegion) MOZ_OVERRIDE; #ifdef MOZ_DUMP_PAINTING - virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; #endif protected: nsRect GetBoundsInternal(); @@ -2352,7 +2389,7 @@ NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR) #ifdef MOZ_DUMP_PAINTING - virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; #endif protected: @@ -2583,10 +2620,19 @@ // this layer. aFrame must have the same reference frame as mFrame. void AddFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame); + // Indicate that an inactive scrollframe's scrollport should be added to the + // dispatch-to-content region, to ensure that APZ lets content create a + // displayport. + void AddInactiveScrollPort(const nsRect& aRect); + const nsRegion& HitRegion() { return mHitRegion; } const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; } const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; } +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; +#endif + private: // Relative to aFrame's reference frame. // These are the points that are definitely in the hit region. @@ -2792,7 +2838,7 @@ bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder); NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY) #ifdef MOZ_DUMP_PAINTING - virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; #endif bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; @@ -3090,7 +3136,7 @@ virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; } #ifdef MOZ_DUMP_PAINTING - virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; #endif bool IsDisplayPortOpaque() { return mDisplayPortContentsOpaque; } @@ -3501,7 +3547,7 @@ bool ShouldPrerender(nsDisplayListBuilder* aBuilder); #ifdef MOZ_DUMP_PAINTING - virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; + virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE; #endif private: @@ -3575,4 +3621,29 @@ nscoord mRightEdge; // length from the right side }; +/** + * A wrapper layer that wraps its children in a container, then renders + * everything with an appropriate VR effect based on the HMDInfo. + */ + +class nsDisplayVR : public nsDisplayOwnLayer { +public: + nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList, mozilla::gfx::VRHMDInfo* aHMD); + + virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE + { + return mozilla::LAYER_ACTIVE; + } + + virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; + +protected: + nsRefPtr mHMD; +}; + #endif /*NSDISPLAYLIST_H_*/ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsDocumentViewer.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsDocumentViewer.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsDocumentViewer.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsDocumentViewer.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -121,6 +121,7 @@ #include #include "mozilla/dom/Element.h" +#include "mozilla/Telemetry.h" using namespace mozilla; using namespace mozilla::dom; @@ -665,7 +666,8 @@ // Initialize our view manager int32_t p2a = mPresContext->AppUnitsPerDevPixel(); - MOZ_ASSERT(p2a == mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel()); + MOZ_ASSERT(p2a == + mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()); nscoord width = p2a * mBounds.width; nscoord height = p2a * mBounds.height; @@ -1198,6 +1200,7 @@ nsAutoSyncOperation sync(mDocument); mInPermitUnloadPrompt = true; + mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_COUNT, 1); rv = prompt->ConfirmEx(title, message, buttonFlags, leaveLabel, stayLabel, nullptr, nullptr, &dummy, &buttonPressed); @@ -1212,12 +1215,15 @@ // XXX: Are there other cases where prompts can abort? Is it ok to // prevent unloading the page in those cases? if (NS_FAILED(rv)) { + mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_ACTION, 2); *aPermitUnload = false; return NS_OK; } // Button 0 == leave, button 1 == stay *aPermitUnload = (buttonPressed == 0); + mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_ACTION, + (*aPermitUnload ? 1 : 0)); // If the user decided to go ahead, make sure not to prompt the user again // by toggling the internal prompting bool to false: if (*aPermitUnload) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsFrameManagerBase.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsFrameManagerBase.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsFrameManagerBase.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsFrameManagerBase.h 2014-11-26 21:46:05.000000000 +0000 @@ -34,6 +34,7 @@ , mStyleSet(nullptr) , mRootFrame(nullptr) , mUndisplayedMap(nullptr) + , mDisplayContentsMap(nullptr) , mIsDestroyingFrames(false) { mPlaceholderMap.ops = nullptr; @@ -65,6 +66,7 @@ nsIFrame* mRootFrame; PLDHashTable mPlaceholderMap; UndisplayedMap* mUndisplayedMap; + UndisplayedMap* mDisplayContentsMap; bool mIsDestroyingFrames; // The frame manager is destroying some frame(s). // The frame tree generation number diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsFrameManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsFrameManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsFrameManager.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsFrameManager.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -40,8 +40,10 @@ #ifdef DEBUG //#define DEBUG_UNDISPLAYED_MAP + //#define DEBUG_DISPLAY_CONTENTS_MAP #else #undef DEBUG_UNDISPLAYED_MAP + #undef DEBUG_DISPLAY_CONTENTS_MAP #endif using namespace mozilla; @@ -96,6 +98,7 @@ UndisplayedNode* aNode); void RemoveNodesFor(nsIContent* aParentContent); + UndisplayedNode* UnlinkNodesFor(nsIContent* aParentContent); // Removes all entries from the hash table void Clear(void); @@ -139,6 +142,8 @@ delete mUndisplayedMap; mUndisplayedMap = nullptr; + delete mDisplayContentsMap; + mDisplayContentsMap = nullptr; mPresShell = nullptr; } @@ -220,14 +225,14 @@ //---------------------------------------------------------------------- -nsStyleContext* -nsFrameManager::GetUndisplayedContent(nsIContent* aContent) +/* static */ nsStyleContext* +nsFrameManager::GetStyleContextInMap(UndisplayedMap* aMap, nsIContent* aContent) { - if (!aContent || !mUndisplayedMap) + if (!aContent) { return nullptr; - + } nsIContent* parent = aContent->GetParent(); - for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(parent); + for (UndisplayedNode* node = aMap->GetFirstNode(parent); node; node = node->mNext) { if (node->mContent == aContent) return node->mStyle; @@ -236,53 +241,69 @@ return nullptr; } +/* static */ UndisplayedNode* +nsFrameManager::GetAllUndisplayedNodesInMapFor(UndisplayedMap* aMap, + nsIContent* aParentContent) +{ + return aMap ? aMap->GetFirstNode(aParentContent) : nullptr; +} + UndisplayedNode* nsFrameManager::GetAllUndisplayedContentIn(nsIContent* aParentContent) { - if (!mUndisplayedMap) - return nullptr; - - return mUndisplayedMap->GetFirstNode(aParentContent); + return GetAllUndisplayedNodesInMapFor(mUndisplayedMap, aParentContent); } -void -nsFrameManager::SetUndisplayedContent(nsIContent* aContent, - nsStyleContext* aStyleContext) +/* static */ void +nsFrameManager::SetStyleContextInMap(UndisplayedMap* aMap, + nsIContent* aContent, + nsStyleContext* aStyleContext) { NS_PRECONDITION(!aStyleContext->GetPseudo(), "Should only have actual elements here"); -#ifdef DEBUG_UNDISPLAYED_MAP +#if defined(DEBUG_UNDISPLAYED_MAP) || defined(DEBUG_DISPLAY_BOX_CONTENTS_MAP) static int i = 0; - printf("SetUndisplayedContent(%d): p=%p \n", i++, (void *)aContent); + printf("SetStyleContextInMap(%d): p=%p \n", i++, (void *)aContent); #endif - NS_ASSERTION(!GetUndisplayedContent(aContent), - "Already have an undisplayed context entry for aContent"); + NS_ASSERTION(!GetStyleContextInMap(aMap, aContent), + "Already have an entry for aContent"); - if (! mUndisplayedMap) { - mUndisplayedMap = new UndisplayedMap; - } nsIContent* parent = aContent->GetParent(); - NS_ASSERTION(parent || (mPresShell && mPresShell->GetDocument() && - mPresShell->GetDocument()->GetRootElement() == aContent), +#ifdef DEBUG + nsIPresShell* shell = aStyleContext->PresContext()->PresShell(); + NS_ASSERTION(parent || (shell && shell->GetDocument() && + shell->GetDocument()->GetRootElement() == aContent), "undisplayed content must have a parent, unless it's the root " "element"); - mUndisplayedMap->AddNodeFor(parent, aContent, aStyleContext); +#endif + aMap->AddNodeFor(parent, aContent, aStyleContext); } void -nsFrameManager::ChangeUndisplayedContent(nsIContent* aContent, - nsStyleContext* aStyleContext) +nsFrameManager::SetUndisplayedContent(nsIContent* aContent, + nsStyleContext* aStyleContext) { - NS_ASSERTION(mUndisplayedMap, "no existing undisplayed content"); - -#ifdef DEBUG_UNDISPLAYED_MAP + if (!mUndisplayedMap) { + mUndisplayedMap = new UndisplayedMap; + } + SetStyleContextInMap(mUndisplayedMap, aContent, aStyleContext); +} + +/* static */ void +nsFrameManager::ChangeStyleContextInMap(UndisplayedMap* aMap, + nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + MOZ_ASSERT(aMap, "expecting a map"); + +#if defined(DEBUG_UNDISPLAYED_MAP) || defined(DEBUG_DISPLAY_BOX_CONTENTS_MAP) static int i = 0; - printf("ChangeUndisplayedContent(%d): p=%p \n", i++, (void *)aContent); + printf("ChangeStyleContextInMap(%d): p=%p \n", i++, (void *)aContent); #endif - for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aContent->GetParent()); + for (UndisplayedNode* node = aMap->GetFirstNode(aContent->GetParent()); node; node = node->mNext) { if (node->mContent == aContent) { node->mStyle = aStyleContext; @@ -290,7 +311,7 @@ } } - NS_NOTREACHED("no existing undisplayed content"); + MOZ_CRASH("couldn't find the entry to change"); } void @@ -321,6 +342,9 @@ node = node->mNext; } } +#ifdef DEBUG_UNDISPLAYED_MAP + printf( "not found.\n"); +#endif } void @@ -348,6 +372,92 @@ } //---------------------------------------------------------------------- + +void +nsFrameManager::SetDisplayContents(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + if (!mDisplayContentsMap) { + mDisplayContentsMap = new UndisplayedMap; + } + SetStyleContextInMap(mDisplayContentsMap, aContent, aStyleContext); +} + +UndisplayedNode* +nsFrameManager::GetAllDisplayContentsIn(nsIContent* aParentContent) +{ + return GetAllUndisplayedNodesInMapFor(mDisplayContentsMap, aParentContent); +} + +void +nsFrameManager::ClearDisplayContentsIn(nsIContent* aContent, + nsIContent* aParentContent) +{ +#ifdef DEBUG_DISPLAY_CONTENTS_MAP + static int i = 0; + printf("ClearDisplayContents(%d): content=%p parent=%p --> ", i++, (void *)aContent, (void*)aParentContent); +#endif + + if (mDisplayContentsMap) { + UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aParentContent); + while (node) { + if (node->mContent == aContent) { + mDisplayContentsMap->RemoveNodeFor(aParentContent, node); + +#ifdef DEBUG_DISPLAY_CONTENTS_MAP + printf( "REMOVED!\n"); +#endif +#ifdef DEBUG + // make sure that there are no more entries for the same content + nsStyleContext* context = GetDisplayContentsStyleFor(aContent); + NS_ASSERTION(context == nullptr, "Found more entries for aContent after removal"); +#endif + ClearAllDisplayContentsIn(aContent); + ClearAllUndisplayedContentIn(aContent); + return; + } + node = node->mNext; + } + } +#ifdef DEBUG_DISPLAY_CONTENTS_MAP + printf( "not found.\n"); +#endif +} + +void +nsFrameManager::ClearAllDisplayContentsIn(nsIContent* aParentContent) +{ +#ifdef DEBUG_DISPLAY_CONTENTS_MAP + static int i = 0; + printf("ClearAllDisplayContentsIn(%d): parent=%p \n", i++, (void*)aParentContent); +#endif + + if (mDisplayContentsMap) { + UndisplayedNode* cur = mDisplayContentsMap->UnlinkNodesFor(aParentContent); + while (cur) { + UndisplayedNode* next = cur->mNext; + cur->mNext = nullptr; + ClearAllDisplayContentsIn(cur->mContent); + ClearAllUndisplayedContentIn(cur->mContent); + delete cur; + cur = next; + } + } + + // Need to look at aParentContent's content list due to XBL insertions. + // Nodes in aParentContent's content list do not have aParentContent as a + // parent, but are treated as children of aParentContent. We iterate over + // the flattened content list and just ignore any nodes we don't care about. + FlattenedChildIterator iter(aParentContent); + for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { + if (child->GetParent() != aParentContent) { + ClearDisplayContentsIn(child, child->GetParent()); + ClearUndisplayedContentIn(child, child->GetParent()); + } + } +} + +//---------------------------------------------------------------------- void nsFrameManager::AppendFrames(nsContainerFrame* aParentFrame, ChildListID aListID, @@ -424,6 +534,7 @@ nsIContent* content = aFrame->GetContent(); if (content && content->GetPrimaryFrame() == aFrame) { ClearAllUndisplayedContentIn(content); + ClearAllDisplayContentsIn(content); } } @@ -700,18 +811,26 @@ delete aNode; } -void -nsFrameManagerBase::UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent) + +UndisplayedNode* +nsFrameManagerBase::UndisplayedMap::UnlinkNodesFor(nsIContent* aParentContent) { PLHashEntry** entry = GetEntryFor(&aParentContent); NS_ASSERTION(entry, "content not in map"); if (*entry) { - UndisplayedNode* node = (UndisplayedNode*)((*entry)->value); + UndisplayedNode* node = (UndisplayedNode*)((*entry)->value); NS_ASSERTION(node, "null node for non-null entry in UndisplayedMap"); - delete node; PL_HashTableRawRemove(mTable, entry, *entry); mLastLookup = nullptr; // hashtable may have shifted bucket out from under us + return node; } + return nullptr; +} + +void +nsFrameManagerBase::UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent) +{ + delete UnlinkNodesFor(aParentContent); } static int diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsFrameManager.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsFrameManager.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsFrameManager.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsFrameManager.h 2014-11-26 21:46:05.000000000 +0000 @@ -108,17 +108,67 @@ void ClearPlaceholderFrameMap(); // Mapping undisplayed content - nsStyleContext* GetUndisplayedContent(nsIContent* aContent); + nsStyleContext* GetUndisplayedContent(nsIContent* aContent) + { + if (!mUndisplayedMap) { + return nullptr; + } + return GetStyleContextInMap(mUndisplayedMap, aContent); + } mozilla::UndisplayedNode* GetAllUndisplayedContentIn(nsIContent* aParentContent); void SetUndisplayedContent(nsIContent* aContent, - nsStyleContext* aStyleContext); + nsStyleContext* aStyleContext); void ChangeUndisplayedContent(nsIContent* aContent, - nsStyleContext* aStyleContext); + nsStyleContext* aStyleContext) + { + ChangeStyleContextInMap(mUndisplayedMap, aContent, aStyleContext); + } + void ClearUndisplayedContentIn(nsIContent* aContent, - nsIContent* aParentContent); + nsIContent* aParentContent); void ClearAllUndisplayedContentIn(nsIContent* aParentContent); + // display:contents related methods: + /** + * Return the registered display:contents style context for aContent, if any. + */ + nsStyleContext* GetDisplayContentsStyleFor(nsIContent* aContent) + { + if (!mDisplayContentsMap) { + return nullptr; + } + return GetStyleContextInMap(mDisplayContentsMap, aContent); + } + + /** + * Return the linked list of UndisplayedNodes containing the registered + * display:contents children of aParentContent, if any. + */ + mozilla::UndisplayedNode* GetAllDisplayContentsIn(nsIContent* aParentContent); + /** + * Register aContent having a display:contents style context. + */ + void SetDisplayContents(nsIContent* aContent, + nsStyleContext* aStyleContext); + /** + * Change the registered style context for aContent to aStyleContext. + */ + void ChangeDisplayContents(nsIContent* aContent, + nsStyleContext* aStyleContext) + { + ChangeStyleContextInMap(mDisplayContentsMap, aContent, aStyleContext); + } + + /** + * Unregister the display:contents style context for aContent, if any. + * If found, then also unregister any display:contents and display:none + * style contexts for its descendants. + */ + void ClearDisplayContentsIn(nsIContent* aContent, + nsIContent* aParentContent); + void ClearAllDisplayContentsIn(nsIContent* aParentContent); + // Functions for manipulating the frame model void AppendFrames(nsContainerFrame* aParentFrame, ChildListID aListID, @@ -161,6 +211,18 @@ void RestoreFrameStateFor(nsIFrame* aFrame, nsILayoutHistoryState* aState); +protected: + static nsStyleContext* GetStyleContextInMap(UndisplayedMap* aMap, + nsIContent* aContent); + static mozilla::UndisplayedNode* + GetAllUndisplayedNodesInMapFor(UndisplayedMap* aMap, + nsIContent* aParentContent); + static void SetStyleContextInMap(UndisplayedMap* aMap, + nsIContent* aContent, + nsStyleContext* aStyleContext); + static void ChangeStyleContextInMap(UndisplayedMap* aMap, + nsIContent* aContent, + nsStyleContext* aStyleContext); }; #endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsIPresShell.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsIPresShell.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsIPresShell.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsIPresShell.h 2014-11-26 21:46:05.000000000 +0000 @@ -1253,9 +1253,10 @@ nsCOMPtr mPendingContent; nsCOMPtr mOverrideContent; bool mReleaseContent; + bool mPrimaryState; - explicit PointerCaptureInfo(nsIContent* aPendingContent) : - mPendingContent(aPendingContent), mReleaseContent(false) + explicit PointerCaptureInfo(nsIContent* aPendingContent, bool aPrimaryState) : + mPendingContent(aPendingContent), mReleaseContent(false), mPrimaryState(aPrimaryState) { MOZ_COUNT_CTOR(PointerCaptureInfo); } @@ -1273,27 +1274,29 @@ // Keeps a map between pointerId and element that currently capturing pointer // with such pointerId. If pointerId is absent in this map then nobody is // capturing it. Additionally keep information about pending capturing content. + // Additionally keep information about primaryState of pointer event. static nsClassHashtable* gPointerCaptureList; struct PointerInfo { bool mActiveState; uint16_t mPointerType; - PointerInfo(bool aActiveState, uint16_t aPointerType) : - mActiveState(aActiveState), mPointerType(aPointerType) {} + bool mPrimaryState; + PointerInfo(bool aActiveState, uint16_t aPointerType, bool aPrimaryState) : + mActiveState(aActiveState), mPointerType(aPointerType), mPrimaryState(aPrimaryState) {} }; - // Keeps information about pointers such as pointerId, activeState, pointerType + // Keeps information about pointers such as pointerId, activeState, pointerType, primaryState static nsClassHashtable* gActivePointersIds; static void DispatchGotOrLostPointerCaptureEvent(bool aIsGotCapture, uint32_t aPointerId, uint16_t aPointerType, + bool aIsPrimary, nsIContent* aCaptureTarget); static void SetPointerCapturingContent(uint32_t aPointerId, nsIContent* aContent); static void ReleasePointerCapturingContent(uint32_t aPointerId, nsIContent* aContent); static nsIContent* GetPointerCapturingContent(uint32_t aPointerId); - static uint16_t GetPointerType(uint32_t aPointerId); - + // CheckPointerCaptureState checks cases, when got/lostpointercapture events should be fired. // Function returns true, if any of events was fired; false, if no one event was fired. static bool CheckPointerCaptureState(uint32_t aPointerId); @@ -1302,6 +1305,12 @@ // aActiveState is additional information, which shows state of pointer like button state for mouse. static bool GetPointerInfo(uint32_t aPointerId, bool& aActiveState); + // GetPointerType returns pointer type like mouse, pen or touch for pointer event with pointerId + static uint16_t GetPointerType(uint32_t aPointerId); + + // GetPointerPrimaryState returns state of attribute isPrimary for pointer event with pointerId + static bool GetPointerPrimaryState(uint32_t aPointerId); + /** * When capturing content is set, it traps all mouse events and retargets * them at this content node. If capturing is not allowed diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsLayoutDebugger.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsLayoutDebugger.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsLayoutDebugger.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsLayoutDebugger.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -191,9 +191,7 @@ } // Display item specific debug info - nsCString itemStr; - aItem->WriteDebugInfo(itemStr); - aStream << itemStr.get(); + aItem->WriteDebugInfo(aStream); if (aDumpHtml && aItem->Painted()) { aStream << ""; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsLayoutUtils.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsLayoutUtils.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsLayoutUtils.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsLayoutUtils.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -9,6 +9,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/BasicEvents.h" #include "mozilla/gfx/PathHelpers.h" +#include "mozilla/Likely.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "nsCharTraits.h" @@ -113,6 +114,7 @@ #define GRID_ENABLED_PREF_NAME "layout.css.grid.enabled" #define RUBY_ENABLED_PREF_NAME "layout.css.ruby.enabled" #define STICKY_ENABLED_PREF_NAME "layout.css.sticky.enabled" +#define DISPLAY_CONTENTS_ENABLED_PREF_NAME "layout.css.display-contents.enabled" #define TEXT_ALIGN_TRUE_ENABLED_PREF_NAME "layout.css.text-align-true-value.enabled" #ifdef DEBUG @@ -294,6 +296,36 @@ isStickyEnabled ? eCSSKeyword_sticky : eCSSKeyword_UNKNOWN; } +// When the pref "layout.css.display-contents.enabled" changes, this function is +// invoked to let us update kDisplayKTable, to selectively disable or restore +// the entries for "contents" in that table. +static void +DisplayContentsEnabledPrefChangeCallback(const char* aPrefName, void* aClosure) +{ + NS_ASSERTION(strcmp(aPrefName, DISPLAY_CONTENTS_ENABLED_PREF_NAME) == 0, + "Did you misspell " DISPLAY_CONTENTS_ENABLED_PREF_NAME " ?"); + + static bool sIsDisplayContentsKeywordIndexInitialized; + static int32_t sIndexOfContentsInDisplayTable; + bool isDisplayContentsEnabled = + Preferences::GetBool(DISPLAY_CONTENTS_ENABLED_PREF_NAME, false); + + if (!sIsDisplayContentsKeywordIndexInitialized) { + // First run: find the position of "contents" in kDisplayKTable. + sIndexOfContentsInDisplayTable = + nsCSSProps::FindIndexOfKeyword(eCSSKeyword_contents, + nsCSSProps::kDisplayKTable); + sIsDisplayContentsKeywordIndexInitialized = true; + } + + // OK -- now, stomp on or restore the "contents" entry in kDisplayKTable, + // depending on whether the pref is enabled vs. disabled. + if (sIndexOfContentsInDisplayTable >= 0) { + nsCSSProps::kDisplayKTable[sIndexOfContentsInDisplayTable] = + isDisplayContentsEnabled ? eCSSKeyword_contents : eCSSKeyword_UNKNOWN; + } +} + // When the pref "layout.css.text-align-true-value.enabled" changes, this // function is called to let us update kTextAlignKTable & kTextAlignLastKTable, // to selectively disable or restore the entries for "true" in those tables. @@ -854,6 +886,9 @@ // Expand the rect by the margins screenRect.Inflate(aMarginsData->mMargins); + int alignmentX = gfxPlatform::GetPlatform()->GetTileWidth(); + int alignmentY = gfxPlatform::GetPlatform()->GetTileHeight(); + // And then align it to the requested alignment. // Note on the correctness of applying the alignment in Screen space: // The correct space to apply the alignment in would be Layer space, but @@ -865,7 +900,7 @@ // screen resolution; since this is what Layout does most of the time, // this is a good approximation. A proper solution would involve moving the // choosing of the resolution to display-list building time. - if (aMarginsData->mAlignmentX > 0 || aMarginsData->mAlignmentY > 0) { + if (alignmentX > 0 && alignmentY > 0) { // Inflate the rectangle by 1 so that we always push to the next tile // boundary. This is desirable to stop from having a rectangle with a // moving origin occasionally being smaller when it coincidentally lines @@ -873,21 +908,21 @@ screenRect.Inflate(1); // Avoid division by zero. - if (aMarginsData->mAlignmentX == 0) { - aMarginsData->mAlignmentX = 1; + if (alignmentX == 0) { + alignmentX = 1; } - if (aMarginsData->mAlignmentY == 0) { - aMarginsData->mAlignmentY = 1; + if (alignmentY == 0) { + alignmentY = 1; } ScreenPoint scrollPosScreen = LayoutDevicePoint::FromAppUnits(scrollPos, auPerDevPixel) * res; screenRect += scrollPosScreen; - float x = aMarginsData->mAlignmentX * floor(screenRect.x / aMarginsData->mAlignmentX); - float y = aMarginsData->mAlignmentY * floor(screenRect.y / aMarginsData->mAlignmentY); - float w = aMarginsData->mAlignmentX * ceil(screenRect.XMost() / aMarginsData->mAlignmentX) - x; - float h = aMarginsData->mAlignmentY * ceil(screenRect.YMost() / aMarginsData->mAlignmentY) - y; + float x = alignmentX * floor(screenRect.x / alignmentX); + float y = alignmentY * floor(screenRect.y / alignmentY); + float w = alignmentX * ceil(screenRect.XMost() / alignmentX) - x; + float h = alignmentY * ceil(screenRect.YMost() / alignmentY) - y; screenRect = ScreenRect(x, y, w, h); screenRect -= scrollPosScreen; } @@ -953,24 +988,22 @@ return GetDisplayPortImpl(aContent, aResult, 1.0f); } -void +bool nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent, nsIPresShell* aPresShell, const ScreenMargin& aMargins, - uint32_t aAlignmentX, - uint32_t aAlignmentY, uint32_t aPriority, RepaintMode aRepaintMode) { DisplayPortMarginsPropertyData* currentData = static_cast(aContent->GetProperty(nsGkAtoms::DisplayPortMargins)); if (currentData && currentData->mPriority > aPriority) { - return; + return false; } aContent->SetProperty(nsGkAtoms::DisplayPortMargins, new DisplayPortMarginsPropertyData( - aMargins, aAlignmentX, aAlignmentY, aPriority), + aMargins, aPriority), nsINode::DeleteProperty); if (nsLayoutUtils::UsesAsyncScrolling()) { @@ -989,6 +1022,8 @@ rootFrame->SchedulePaint(); } } + + return true; } void @@ -1026,73 +1061,6 @@ return static_cast(f); } -/** - * GetFirstChildFrame returns the first "real" child frame of a - * given frame. It will descend down into pseudo-frames (unless the - * pseudo-frame is the :before generated frame). - * @param aFrame the frame - * @param aFrame the frame's content node - */ -static nsIFrame* -GetFirstChildFrame(nsIFrame* aFrame, - nsIContent* aContent) -{ - NS_PRECONDITION(aFrame, "NULL frame pointer"); - - // Get the first child frame - nsIFrame* childFrame = aFrame->GetFirstPrincipalChild(); - - // If the child frame is a pseudo-frame, then return its first child. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case - if (childFrame && - childFrame->IsPseudoFrame(aContent) && - !childFrame->IsGeneratedContentFrame()) { - return GetFirstChildFrame(childFrame, aContent); - } - - return childFrame; -} - -/** - * GetLastChildFrame returns the last "real" child frame of a - * given frame. It will descend down into pseudo-frames (unless the - * pseudo-frame is the :after generated frame). - * @param aFrame the frame - * @param aFrame the frame's content node - */ -static nsIFrame* -GetLastChildFrame(nsContainerFrame* aFrame, - nsIContent* aContent) -{ - NS_PRECONDITION(aFrame, "NULL frame pointer"); - - // Get the last continuation frame that's a parent - nsContainerFrame* lastParentContinuation = - nsLayoutUtils::LastContinuationWithChild(aFrame); - nsIFrame* lastChildFrame = - lastParentContinuation->GetLastChild(nsIFrame::kPrincipalList); - if (lastChildFrame) { - // Get the frame's first continuation. This matters in case the frame has - // been continued across multiple lines or split by BiDi resolution. - lastChildFrame = lastChildFrame->FirstContinuation(); - - // If the last child frame is a pseudo-frame, then return its last child. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case - if (lastChildFrame && - lastChildFrame->IsPseudoFrame(aContent) && - !lastChildFrame->IsGeneratedContentFrame()) { - return GetLastChildFrame(static_cast(lastChildFrame), - aContent); - } - - return lastChildFrame; - } - - return nullptr; -} - //static FrameChildListID nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame) @@ -1191,46 +1159,81 @@ return id; } -// static -nsIFrame* -nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame) +/*static*/ nsIFrame* +nsLayoutUtils::GetBeforeFrameForContent(nsIFrame* aFrame, + nsIContent* aContent) { - NS_PRECONDITION(aFrame, "NULL frame pointer"); - NS_ASSERTION(!aFrame->GetPrevContinuation(), - "aFrame must be first continuation"); - - nsIFrame* cif = aFrame->GetContentInsertionFrame(); - if (!cif) { + nsContainerFrame* genConParentFrame = aFrame->GetContentInsertionFrame(); + if (!genConParentFrame) { return nullptr; } - nsIFrame* firstFrame = GetFirstChildFrame(cif, aFrame->GetContent()); - if (firstFrame && IsGeneratedContentFor(nullptr, firstFrame, - nsCSSPseudoElements::before)) { - return firstFrame; + nsTArray* prop = genConParentFrame->GetGenConPseudos(); + if (prop) { + const nsTArray& pseudos(*prop); + for (uint32_t i = 0; i < pseudos.Length(); ++i) { + if (pseudos[i]->GetParent() == aContent && + pseudos[i]->Tag() == nsGkAtoms::mozgeneratedcontentbefore) { + return pseudos[i]->GetPrimaryFrame(); + } + } + } + // If the first child frame is a pseudo-frame, then try that. + // Note that the frame we create for the generated content is also a + // pseudo-frame and so don't drill down in that case. + nsIFrame* childFrame = genConParentFrame->GetFirstPrincipalChild(); + if (childFrame && + childFrame->IsPseudoFrame(aContent) && + !childFrame->IsGeneratedContentFrame()) { + return GetBeforeFrameForContent(childFrame, aContent); } - return nullptr; } -// static -nsIFrame* -nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame) +/*static*/ nsIFrame* +nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame) { - NS_PRECONDITION(aFrame, "NULL frame pointer"); + return GetBeforeFrameForContent(aFrame, aFrame->GetContent()); +} - nsContainerFrame* cif = aFrame->GetContentInsertionFrame(); - if (!cif) { +/*static*/ nsIFrame* +nsLayoutUtils::GetAfterFrameForContent(nsIFrame* aFrame, + nsIContent* aContent) +{ + nsContainerFrame* genConParentFrame = aFrame->GetContentInsertionFrame(); + if (!genConParentFrame) { return nullptr; } - nsIFrame* lastFrame = GetLastChildFrame(cif, aFrame->GetContent()); - if (lastFrame && IsGeneratedContentFor(nullptr, lastFrame, - nsCSSPseudoElements::after)) { - return lastFrame; + nsTArray* prop = genConParentFrame->GetGenConPseudos(); + if (prop) { + const nsTArray& pseudos(*prop); + for (uint32_t i = 0; i < pseudos.Length(); ++i) { + if (pseudos[i]->GetParent() == aContent && + pseudos[i]->Tag() == nsGkAtoms::mozgeneratedcontentafter) { + return pseudos[i]->GetPrimaryFrame(); + } + } + } + // If the last child frame is a pseudo-frame, then try that. + // Note that the frame we create for the generated content is also a + // pseudo-frame and so don't drill down in that case. + nsIFrame* lastParentContinuation = + nsLayoutUtils::LastContinuationWithChild(genConParentFrame); + nsIFrame* childFrame = + lastParentContinuation->GetLastChild(nsIFrame::kPrincipalList); + if (childFrame && + childFrame->IsPseudoFrame(aContent) && + !childFrame->IsGeneratedContentFrame()) { + return GetAfterFrameForContent(childFrame->FirstContinuation(), aContent); } - return nullptr; } +/*static*/ nsIFrame* +nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame) +{ + return GetAfterFrameForContent(aFrame, aFrame->GetContent()); +} + // static nsIFrame* nsLayoutUtils::GetClosestFrameOfType(nsIFrame* aFrame, nsIAtom* aFrameType) @@ -1717,8 +1720,8 @@ reinterpret_cast(intptr_t(aLayerize))); } -static bool -IsScrollbarThumbLayerized(nsIFrame* aThumbFrame) +bool +nsLayoutUtils::IsScrollbarThumbLayerized(nsIFrame* aThumbFrame) { return reinterpret_cast(aThumbFrame->Properties().Get(ScrollbarThumbLayerized())); } @@ -1728,55 +1731,7 @@ nsIFrame* aFrame, const nsIFrame* aStopAtAncestor) { - nsIFrame* f = aFrame; - nsIFrame* stickyFrame = nullptr; - while (f != aStopAtAncestor) { - if (nsLayoutUtils::IsPopup(f)) - break; - if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(f)) - break; - if (!f->GetParent() && - nsLayoutUtils::ViewportHasDisplayPort(f->PresContext())) { - // Viewport frames in a display port need to be animated geometry roots - // for background-attachment:fixed elements. - break; - } - nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(f); - if (!parent) - break; - nsIAtom* parentType = parent->GetType(); - // Treat the slider thumb as being as an active scrolled root when it wants - // its own layer so that it can move without repainting. - if (parentType == nsGkAtoms::sliderFrame && IsScrollbarThumbLayerized(f)) { - break; - } - // Sticky frames are active if their nearest scrollable frame - // is also active, just keep a record of sticky frames that we - // encounter for now. - if (f->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY && - !stickyFrame) { - stickyFrame = f; - } - if (parentType == nsGkAtoms::scrollFrame) { - nsIScrollableFrame* sf = do_QueryFrame(parent); - if (sf->IsScrollingActive(aBuilder) && sf->GetScrolledFrame() == f) { - // If we found a sticky frame inside this active scroll frame, - // then use that. Otherwise use the scroll frame. - if (stickyFrame) { - return stickyFrame; - } - return f; - } else { - stickyFrame = nullptr; - } - } - // Fixed-pos frames are parented by the viewport frame, which has no parent - if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(f)) { - return f; - } - f = parent; - } - return f; + return aBuilder->FindAnimatedGeometryRootFor(aFrame, aStopAtAncestor); } nsIFrame* @@ -1837,12 +1792,24 @@ f->GetParent() : nsLayoutUtils::GetCrossDocParentFrame(f)) { nsIScrollableFrame* scrollableFrame = do_QueryFrame(f); if (scrollableFrame) { + if (aFlags & SCROLLABLE_ONLY_ASYNC_SCROLLABLE) { + if (scrollableFrame->WantAsyncScroll()) { + return scrollableFrame; + } + continue; + } ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); if ((aFlags & SCROLLABLE_INCLUDE_HIDDEN) || ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) return scrollableFrame; } + if (aFlags & SCROLLABLE_ALWAYS_MATCH_ROOT) { + nsPresContext* pc = f->PresContext(); + if (pc->IsRootContentDocument() && pc->PresShell()->GetRootScrollFrame() == f) { + return scrollableFrame; + } + } } return nullptr; } @@ -2772,20 +2739,22 @@ return NS_OK; } -// aScrollFrame and aScrollFrameAsScrollable must be non-nullptr +// aScrollFrameAsScrollable must be non-nullptr and queryable to an nsIFrame static FrameMetrics -CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, - nsIScrollableFrame* aScrollFrameAsScrollable) { +CalculateFrameMetricsForDisplayPort(nsIScrollableFrame* aScrollFrame) { + nsIFrame* frame = do_QueryFrame(aScrollFrame); + MOZ_ASSERT(frame); + // Calculate the metrics necessary for calculating the displayport. // This code has a lot in common with the code in ComputeFrameMetrics(); // we may want to refactor this at some point. FrameMetrics metrics; - nsPresContext* presContext = aScrollFrame->PresContext(); + nsPresContext* presContext = frame->PresContext(); nsIPresShell* presShell = presContext->PresShell(); CSSToLayoutDeviceScale deviceScale(float(nsPresContext::AppUnitsPerCSSPixel()) / presContext->AppUnitsPerDevPixel()); float resolution = 1.0f; - if (aScrollFrame == presShell->GetRootScrollFrame()) { + if (frame == presShell->GetRootScrollFrame()) { // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. resolution = presShell->GetXResolution(); @@ -2798,7 +2767,7 @@ // and leaving mExtraResolution at 1. LayoutDeviceToLayerScale cumulativeResolution( presShell->GetCumulativeResolution().width - * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); + * nsLayoutUtils::GetTransformToAncestorScale(frame).width); LayerToParentLayerScale layerToParentLayerScale(1.0f); metrics.mDevPixelsPerCSSPixel = deviceScale; @@ -2808,9 +2777,9 @@ // Only the size of the composition bounds is relevant to the // displayport calculation, not its origin. - nsSize compositionSize = nsLayoutUtils::CalculateCompositionSizeForFrame(aScrollFrame); + nsSize compositionSize = nsLayoutUtils::CalculateCompositionSizeForFrame(frame); LayoutDeviceToParentLayerScale compBoundsScale(1.0f); - if (aScrollFrame == presShell->GetRootScrollFrame() && presContext->IsRootContentDocument()) { + if (frame == presShell->GetRootScrollFrame() && presContext->IsRootContentDocument()) { if (presContext->GetParentPresContext()) { gfxSize res = presContext->GetParentPresContext()->PresShell()->GetCumulativeResolution(); compBoundsScale = LayoutDeviceToParentLayerScale(res.width, res.height); @@ -2824,18 +2793,34 @@ * compBoundsScale; metrics.SetRootCompositionSize( - nsLayoutUtils::CalculateRootCompositionSize(aScrollFrame, false, metrics)); + nsLayoutUtils::CalculateRootCompositionSize(frame, false, metrics)); metrics.SetScrollOffset(CSSPoint::FromAppUnits( - aScrollFrameAsScrollable->GetScrollPosition())); + aScrollFrame->GetScrollPosition())); metrics.mScrollableRect = CSSRect::FromAppUnits( - nsLayoutUtils::CalculateScrollableRectForFrame(aScrollFrameAsScrollable, nullptr)); + nsLayoutUtils::CalculateScrollableRectForFrame(aScrollFrame, nullptr)); return metrics; } bool +nsLayoutUtils::CalculateAndSetDisplayPortMargins(nsIScrollableFrame* aScrollFrame, + RepaintMode aRepaintMode) { + nsIFrame* frame = do_QueryFrame(aScrollFrame); + MOZ_ASSERT(frame); + nsIContent* content = frame->GetContent(); + MOZ_ASSERT(content); + + FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame); + ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( + metrics, ParentLayerPoint(0.0f, 0.0f), 0.0); + nsIPresShell* presShell = frame->PresContext()->GetPresShell(); + return nsLayoutUtils::SetDisplayPortMargins( + content, presShell, displayportMargins, 0, aRepaintMode); +} + +bool nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, nsIFrame* aScrollFrame, nsRect aDisplayPortBase, @@ -2865,16 +2850,7 @@ // If we don't already have a displayport, calculate and set one. if (!haveDisplayPort) { - FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame, scrollableFrame); - ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( - metrics, ParentLayerPoint(0.0f, 0.0f), 0.0); - nsIPresShell* presShell = aScrollFrame->PresContext()->GetPresShell(); - gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() - ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : - gfx::IntSize(0, 0); - nsLayoutUtils::SetDisplayPortMargins( - content, presShell, displayportMargins, alignment.width, - alignment.height, 0, nsLayoutUtils::RepaintMode::DoNotRepaint); + CalculateAndSetDisplayPortMargins(scrollableFrame, nsLayoutUtils::RepaintMode::DoNotRepaint); haveDisplayPort = GetDisplayPort(content, aOutDisplayport); NS_ASSERTION(haveDisplayPort, "should have a displayport after having just set it"); } @@ -3466,6 +3442,218 @@ return resultRect; } +enum ObjectDimensionType { eWidth, eHeight }; +static nscoord +ComputeMissingDimension(const nsSize& aDefaultObjectSize, + const nsSize& aIntrinsicRatio, + const Maybe& aSpecifiedWidth, + const Maybe& aSpecifiedHeight, + ObjectDimensionType aDimensionToCompute) +{ + // The "default sizing algorithm" computes the missing dimension as follows: + // (source: http://dev.w3.org/csswg/css-images-3/#default-sizing ) + + // 1. "If the object has an intrinsic aspect ratio, the missing dimension of + // the concrete object size is calculated using the intrinsic aspect + // ratio and the present dimension." + if (aIntrinsicRatio.width > 0 && aIntrinsicRatio.height > 0) { + // Fill in the missing dimension using the intrinsic aspect ratio. + nscoord knownDimensionSize; + float ratio; + if (aDimensionToCompute == eWidth) { + knownDimensionSize = *aSpecifiedHeight; + ratio = aIntrinsicRatio.width / aIntrinsicRatio.height; + } else { + knownDimensionSize = *aSpecifiedWidth; + ratio = aIntrinsicRatio.height / aIntrinsicRatio.width; + } + return NSCoordSaturatingNonnegativeMultiply(knownDimensionSize, ratio); + } + + // 2. "Otherwise, if the missing dimension is present in the object’s + // intrinsic dimensions, [...]" + // NOTE: *Skipping* this case, because we already know it's not true -- we're + // in this function because the missing dimension is *not* present in + // the object's intrinsic dimensions. + + // 3. "Otherwise, the missing dimension of the concrete object size is taken + // from the default object size. " + return (aDimensionToCompute == eWidth) ? + aDefaultObjectSize.width : aDefaultObjectSize.height; +} + +/* + * This computes & returns the concrete object size of replaced content, if + * that content were to be rendered with "object-fit: none". (Or, if the + * element has neither an intrinsic height nor width, this method returns an + * empty Maybe<> object.) + * + * As specced... + * http://dev.w3.org/csswg/css-images-3/#valdef-object-fit-none + * ..we use "the default sizing algorithm with no specified size, + * and a default object size equal to the replaced element's used width and + * height." + * + * The default sizing algorithm is described here: + * http://dev.w3.org/csswg/css-images-3/#default-sizing + * Quotes in the function-impl are taken from that ^ spec-text. + * + * Per its final bulleted section: since there's no specified size, + * we run the default sizing algorithm using the object's intrinsic size in + * place of the specified size. But if the object has neither an intrinsic + * height nor an intrinsic width, then we instead return without populating our + * outparam, and we let the caller figure out the size (using a contain + * constraint). + */ +static Maybe +MaybeComputeObjectFitNoneSize(const nsSize& aDefaultObjectSize, + const IntrinsicSize& aIntrinsicSize, + const nsSize& aIntrinsicRatio) +{ + // "If the object has an intrinsic height or width, its size is resolved as + // if its intrinsic dimensions were given as the specified size." + // + // So, first we check if we have an intrinsic height and/or width: + Maybe specifiedWidth; + if (aIntrinsicSize.width.GetUnit() == eStyleUnit_Coord) { + specifiedWidth.emplace(aIntrinsicSize.width.GetCoordValue()); + } + + Maybe specifiedHeight; + if (aIntrinsicSize.height.GetUnit() == eStyleUnit_Coord) { + specifiedHeight.emplace(aIntrinsicSize.height.GetCoordValue()); + } + + Maybe noneSize; // (the value we'll return) + if (specifiedWidth || specifiedHeight) { + // We have at least one specified dimension; use whichever dimension is + // specified, and compute the other one using our intrinsic ratio, or (if + // no valid ratio) using the default object size. + noneSize.emplace(); + + noneSize->width = specifiedWidth ? + *specifiedWidth : + ComputeMissingDimension(aDefaultObjectSize, aIntrinsicRatio, + specifiedWidth, specifiedHeight, + eWidth); + + noneSize->height = specifiedHeight ? + *specifiedHeight : + ComputeMissingDimension(aDefaultObjectSize, aIntrinsicRatio, + specifiedWidth, specifiedHeight, + eHeight); + } + // [else:] "Otherwise [if there's neither an intrinsic height nor width], its + // size is resolved as a contain constraint against the default object size." + // We'll let our caller do that, to share code & avoid redundant + // computations; so, we return w/out populating noneSize. + return noneSize; +} + +// Computes the concrete object size to render into, as described at +// http://dev.w3.org/csswg/css-images-3/#concrete-size-resolution +static nsSize +ComputeConcreteObjectSize(const nsSize& aConstraintSize, + const IntrinsicSize& aIntrinsicSize, + const nsSize& aIntrinsicRatio, + uint8_t aObjectFit) +{ + // Handle default behavior (filling the container) w/ fast early return. + // (Also: if there's no valid intrinsic ratio, then we have the "fill" + // behavior & just use the constraint size.) + if (MOZ_LIKELY(aObjectFit == NS_STYLE_OBJECT_FIT_FILL) || + aIntrinsicRatio.width == 0 || + aIntrinsicRatio.height == 0) { + return aConstraintSize; + } + + // The type of constraint to compute (cover/contain), if needed: + Maybe fitType; + + Maybe noneSize; + if (aObjectFit == NS_STYLE_OBJECT_FIT_NONE || + aObjectFit == NS_STYLE_OBJECT_FIT_SCALE_DOWN) { + noneSize = MaybeComputeObjectFitNoneSize(aConstraintSize, aIntrinsicSize, + aIntrinsicRatio); + if (!noneSize || aObjectFit == NS_STYLE_OBJECT_FIT_SCALE_DOWN) { + // Need to compute a 'CONTAIN' constraint (either for the 'none' size + // itself, or for comparison w/ the 'none' size to resolve 'scale-down'.) + fitType.emplace(nsImageRenderer::CONTAIN); + } + } else if (aObjectFit == NS_STYLE_OBJECT_FIT_COVER) { + fitType.emplace(nsImageRenderer::COVER); + } else if (aObjectFit == NS_STYLE_OBJECT_FIT_CONTAIN) { + fitType.emplace(nsImageRenderer::CONTAIN); + } + + Maybe constrainedSize; + if (fitType) { + constrainedSize.emplace( + nsImageRenderer::ComputeConstrainedSize(aConstraintSize, + aIntrinsicRatio, + *fitType)); + } + + // Now, we should have all the sizing information that we need. + switch (aObjectFit) { + // skipping NS_STYLE_OBJECT_FIT_FILL; we handled it w/ early-return. + case NS_STYLE_OBJECT_FIT_CONTAIN: + case NS_STYLE_OBJECT_FIT_COVER: + MOZ_ASSERT(constrainedSize); + return *constrainedSize; + + case NS_STYLE_OBJECT_FIT_NONE: + if (noneSize) { + return *noneSize; + } + MOZ_ASSERT(constrainedSize); + return *constrainedSize; + + case NS_STYLE_OBJECT_FIT_SCALE_DOWN: + MOZ_ASSERT(constrainedSize); + if (noneSize) { + constrainedSize->width = + std::min(constrainedSize->width, noneSize->width); + constrainedSize->height = + std::min(constrainedSize->height, noneSize->height); + } + return *constrainedSize; + + default: + MOZ_ASSERT_UNREACHABLE("Unexpected enum value for 'object-fit'"); + return aConstraintSize; // fall back to (default) 'fill' behavior + } +} + +/* static */ nsRect +nsLayoutUtils::ComputeObjectDestRect(const nsRect& aConstraintRect, + const IntrinsicSize& aIntrinsicSize, + const nsSize& aIntrinsicRatio, + const nsStylePosition* aStylePos) +{ + // Step 1: Figure out our "concrete object size" + // (the size of the region we'll actually draw our image's pixels into). + nsSize concreteObjectSize = + ComputeConcreteObjectSize(aConstraintRect.Size(), aIntrinsicSize, + aIntrinsicRatio, aStylePos->mObjectFit); + + // Step 2: Figure out how to align that region in the element's content-box. + nsPoint imageTopLeftPt, imageAnchorPt; + nsImageRenderer::ComputeObjectAnchorPoint(aStylePos->mObjectPosition, + aConstraintRect.Size(), + concreteObjectSize, + &imageTopLeftPt, &imageAnchorPt); + // Right now, we're with respect to aConstraintRect's top-left point. We add + // that point here, to convert to the same broader coordinate space that + // aConstraintRect is in. + imageTopLeftPt += aConstraintRect.TopLeft(); + imageAnchorPt += aConstraintRect.TopLeft(); + + // XXXdholbert Per bug 1098417, we should be returning imageAnchorPt here, + // and our caller should make sure it's pixel-aligned. + return nsRect(imageTopLeftPt, concreteObjectSize); +} + nsresult nsLayoutUtils::GetFontMetricsForFrame(const nsIFrame* aFrame, nsFontMetrics** aFontMetrics, @@ -6459,6 +6647,10 @@ StickyEnabledPrefChangeCallback(STICKY_ENABLED_PREF_NAME, nullptr); Preferences::RegisterCallback(TextAlignTrueEnabledPrefChangeCallback, TEXT_ALIGN_TRUE_ENABLED_PREF_NAME); + Preferences::RegisterCallback(DisplayContentsEnabledPrefChangeCallback, + DISPLAY_CONTENTS_ENABLED_PREF_NAME); + DisplayContentsEnabledPrefChangeCallback(DISPLAY_CONTENTS_ENABLED_PREF_NAME, + nullptr); TextAlignTrueEnabledPrefChangeCallback(TEXT_ALIGN_TRUE_ENABLED_PREF_NAME, nullptr); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsLayoutUtils.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsLayoutUtils.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/nsLayoutUtils.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/nsLayoutUtils.h 2014-11-26 21:46:05.000000000 +0000 @@ -96,16 +96,11 @@ struct DisplayPortMarginsPropertyData { DisplayPortMarginsPropertyData(const ScreenMargin& aMargins, - uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority) : mMargins(aMargins) - , mAlignmentX(aAlignmentX) - , mAlignmentY(aAlignmentY) , mPriority(aPriority) {} ScreenMargin mMargins; - uint32_t mAlignmentX; - uint32_t mAlignmentY; uint32_t mPriority; }; @@ -122,6 +117,7 @@ typedef mozilla::dom::DOMRectList DOMRectList; typedef mozilla::layers::Layer Layer; typedef mozilla::ContainerLayerParameters ContainerLayerParameters; + typedef mozilla::IntrinsicSize IntrinsicSize; typedef mozilla::gfx::SourceSurface SourceSurface; typedef mozilla::gfx::Color Color; typedef mozilla::gfx::DrawTarget DrawTarget; @@ -185,12 +181,11 @@ * @param aPriority a priority value to determine which margins take effect * when multiple callers specify margins * @param aRepaintMode whether to schedule a paint after setting the margins + * @return true if the new margins were applied. */ - static void SetDisplayPortMargins(nsIContent* aContent, + static bool SetDisplayPortMargins(nsIContent* aContent, nsIPresShell* aPresShell, const ScreenMargin& aMargins, - uint32_t aAlignmentX, - uint32_t aAlignmentY, uint32_t aPriority = 0, RepaintMode aRepaintMode = RepaintMode::Repaint); @@ -215,22 +210,47 @@ static mozilla::layout::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame); /** - * GetBeforeFrame returns the outermost :before frame of the given frame, if + * GetBeforeFrameForContent returns the ::before frame for aContent, if * one exists. This is typically O(1). The frame passed in must be * the first-in-flow. * - * @param aFrame the frame whose :before is wanted + * @param aGenConParentFrame an ancestor of the ::before frame + * @param aContent the content whose ::before is wanted + * @return the ::before frame or nullptr if there isn't one + */ + static nsIFrame* GetBeforeFrameForContent(nsIFrame* aGenConParentFrame, + nsIContent* aContent); + + /** + * GetBeforeFrame returns the outermost ::before frame of the given frame, if + * one exists. This is typically O(1). The frame passed in must be + * the first-in-flow. + * + * @param aFrame the frame whose ::before is wanted * @return the :before frame or nullptr if there isn't one */ static nsIFrame* GetBeforeFrame(nsIFrame* aFrame); /** - * GetAfterFrame returns the outermost :after frame of the given frame, if one + * GetAfterFrameForContent returns the ::after frame for aContent, if one + * exists. This will walk the in-flow chain of aGenConParentFrame to the + * last-in-flow if needed. This function is typically O(N) in the number + * of child frames, following in-flows, etc. + * + * @param aGenConParentFrame an ancestor of the ::after frame + * @param aContent the content whose ::after is wanted + * @return the ::after frame or nullptr if there isn't one + */ + static nsIFrame* GetAfterFrameForContent(nsIFrame* aGenConParentFrame, + nsIContent* aContent); + + /** + * GetAfterFrame returns the outermost ::after frame of the given frame, if one * exists. This will walk the in-flow chain to the last-in-flow if * needed. This function is typically O(N) in the number of child * frames, following in-flows, etc. * - * @param aFrame the frame whose :after is wanted + * @param aFrame the frame whose ::after is wanted * @return the :after frame or nullptr if there isn't one */ static nsIFrame* GetAfterFrame(nsIFrame* aFrame); @@ -494,6 +514,12 @@ static void SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize); /** + * Returns whether aThumbFrame wants its own layer due to having called + * SetScrollbarThumbLayerization. + */ + static bool IsScrollbarThumbLayerized(nsIFrame* aThumbFrame); + + /** * Finds the nearest ancestor frame to aItem that is considered to have (or * will have) "animated geometry". For example the scrolled frames of * scrollframes which are actively being scrolled fall into this category. @@ -542,8 +568,27 @@ Direction aDirection); enum { + /** + * If the SCROLLABLE_SAME_DOC flag is set, then we only walk the frame tree + * up to the root frame in the current document. + */ SCROLLABLE_SAME_DOC = 0x01, - SCROLLABLE_INCLUDE_HIDDEN = 0x02 + /** + * If the SCROLLABLE_INCLUDE_HIDDEN flag is set then we allow + * overflow:hidden scrollframes to be returned as scrollable frames. + */ + SCROLLABLE_INCLUDE_HIDDEN = 0x02, + /** + * If the SCROLLABLE_ONLY_ASYNC_SCROLLABLE flag is set, then we only + * want to match scrollable frames for which WantAsyncScroll() returns + * true. + */ + SCROLLABLE_ONLY_ASYNC_SCROLLABLE = 0x04, + /** + * If the SCROLLABLE_ALWAYS_MATCH_ROOT flag is set, then return the + * root scrollable frame for the root content document if we hit it. + */ + SCROLLABLE_ALWAYS_MATCH_ROOT = 0x08, }; /** * GetNearestScrollableFrame locates the first ancestor of aFrame @@ -1087,6 +1132,32 @@ uint32_t aFlags = 0); /** + * Computes the destination rect that a given replaced element should render + * into, based on its CSS 'object-fit' and 'object-position' properties. + * + * @param aConstraintRect The constraint rect that we have at our disposal, + * which would e.g. be exactly filled by the image + * if we had "object-fit: fill". + * @param aIntrinsicSize The replaced content's intrinsic size, as reported + * by nsIFrame::GetIntrinsicSize(). + * @param aIntrinsicRatio The replaced content's intrinsic ratio, as reported + * by nsIFrame::GetIntrinsicRatio(). + * @param aStylePos The nsStylePosition struct that contains the 'object-fit' + * and 'object-position' values that we should rely on. + * (This should usually be the nsStylePosition for the + * replaced element in question, but not always. For + * example, a - Test for Bugs 977003, 1094913 + Test for Bugs 977003, 1094913, 1098139 @@ -19,9 +20,11 @@ var test_send_got = 0; var test_got_async = 0; var test_got_type = ""; + var test_got_primary = false; var test_send_lost = 0; var test_lost_async = 0; var test_lost_type = ""; + var test_lost_primary = false; function DownHandler(event) { logger("Receive event: " + event.type); @@ -35,6 +38,7 @@ if(test_send_got) test_got_async++; test_got_type = event.pointerType; + test_got_primary = event.isPrimary; logger("Send releasePointerCapture from target"); target.releasePointerCapture(event.pointerId); logger("releasePointerCapture was executed"); @@ -45,6 +49,7 @@ if(test_send_lost) test_lost_async++; test_lost_type = event.pointerType; + test_lost_primary = event.isPrimary; } function logger(message) { console.log(message); @@ -71,9 +76,11 @@ parent.is(test_send_got, 1, "Part 1: gotpointercapture event should be sent once"); parent.is(test_got_async, 1, "Part 1: gotpointercapture event should be asynchronous"); parent.is(test_got_type, "mouse", "Part 1: gotpointercapture event should have pointerType mouse"); + parent.is(test_got_primary, true, "Part 1: gotpointercapture event should have isPrimary as true"); parent.is(test_send_lost, 1, "Part 1: lostpointercapture event should be sent once"); parent.is(test_lost_async, 1, "Part 1: lostpointercapture event should be asynchronous"); parent.is(test_lost_type, "mouse", "Part 1: lostpointercapture event should have pointerType mouse"); + parent.is(test_lost_primary, true, "Part 1: lostpointercapture event should have isPrimary as true"); logger("finishTest"); parent.finishTest(); } @@ -82,6 +89,7 @@ Mozilla Bug 977003 Test 1
Mozilla Bug 1094913 +
Mozilla Bug 1098139

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/tests/bug977003_inner_5.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/tests/bug977003_inner_5.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/tests/bug977003_inner_5.html 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/tests/bug977003_inner_5.html 2014-11-26 21:46:05.000000000 +0000 @@ -4,10 +4,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=977003 https://bugzilla.mozilla.org/show_bug.cgi?id=1073563 https://bugzilla.mozilla.org/show_bug.cgi?id=1094913 +https://bugzilla.mozilla.org/show_bug.cgi?id=1098139 --> - Test for Bugs 977003, 1073563, 1094913 + Test for Bugs 977003, 1073563, 1094913, 1098139 @@ -21,9 +22,11 @@ var test_down_target = false; var test_got_listener = false; var test_got_type = ""; + var test_got_primary = false; var test_lost_listener = false; var test_lost_type = ""; var test_listener = false; + var test_lost_primary = false; function TargetDownHandler(event) { logger("Target receive event: " + event.type); @@ -37,11 +40,13 @@ listener.releasePointerCapture(event.pointerId); test_got_listener = true; test_got_type = event.pointerType; + test_got_primary = event.isPrimary; } function ListenerLostPCHandler(event) { logger("Receive event on Listener: " + event.type + "(" + event.pointerType + ")"); test_lost_listener = true; test_lost_type = event.pointerType; + test_lost_primary = event.isPrimary; } function ListenerHandler(event) { logger("Receive event on Listener: " + event.type); @@ -69,17 +74,19 @@ listener.addEventListener("pointerup", ListenerHandler, false); listener.addEventListener("pointerout", ListenerHandler, false); var rect = target.getBoundingClientRect(); - synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown", inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH}); - synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove", inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH}); - synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup", inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH}); + synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH}); + synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH}); + synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH}); finishTest(); } function finishTest() { parent.is(test_down_target, true, "Part 5: pointerdown event should be received by target"); parent.is(test_got_listener, true, "Part 5: listener should receive gotpointercapture event"); parent.is(test_got_type, "touch", "Part 5: gotpointercapture event should have pointerType touch"); + parent.is(test_got_primary, true, "Part 5: gotpointercapture event should have isPrimary as true"); parent.is(test_lost_listener, true, "Part 5: listener should receive lostpointercapture event"); parent.is(test_lost_type, "touch", "Part 5: lostpointercapture event should have pointerType touch"); + parent.is(test_lost_primary, true, "Part 5: lostpointercapture event should have isPrimary as true"); parent.is(test_listener, false, "Part 5: listener should not receive any other events"); logger("finishTest"); parent.finishTest(); @@ -90,6 +97,7 @@ Mozilla Bug 977003 Test 5
Mozilla Bug 1073563
Mozilla Bug 1094913 +
Mozilla Bug 1098139

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/tests/marionette/test_selectioncarets_multiplerange.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/tests/marionette/test_selectioncarets_multiplerange.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/tests/marionette/test_selectioncarets_multiplerange.py 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/tests/marionette/test_selectioncarets_multiplerange.py 2014-11-26 21:46:05.000000000 +0000 @@ -7,6 +7,7 @@ from marionette import Actions from marionette_test import MarionetteTestCase from selection import SelectionManager +from gestures import long_press_without_contextmenu class SelectionCaretsMultipleRangeTest(MarionetteTestCase): @@ -36,10 +37,6 @@ self._sel6 = self.marionette.find_element(By.ID, 'sel6') self._nonsel1 = self.marionette.find_element(By.ID, 'nonsel1') - def _long_press_without_contextmenu(self, el, x, y): - return self.actions.press(el, x, y).move_by_offset(0, 0).\ - wait(self._long_press_time).release() - def _long_press_to_select_word(self, el, wordOrdinal): sel = SelectionManager(el) original_content = sel.content @@ -61,7 +58,7 @@ # Long press the caret position. Selection carets should appear, and the # word will be selected. On Windows, those spaces after the word # will also be selected. - self._long_press_without_contextmenu(el, x, y).perform() + long_press_without_contextmenu(self.marionette, el, self._long_press_time, x, y) def _to_unix_line_ending(self, s): """Changes all Windows/Mac line endings in s to UNIX line endings.""" @@ -74,7 +71,7 @@ self.openTestHtml(enabled=True) halfY = self._nonsel1.size['height'] / 2 - self._long_press_without_contextmenu(self._nonsel1, 0, halfY).perform() + long_press_without_contextmenu(self.marionette, self._nonsel1, self._long_press_time, 0, halfY) sel = SelectionManager(self._nonsel1) range_count = sel.range_count() self.assertEqual(range_count, 0) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/tests/marionette/test_selectioncarets.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/tests/marionette/test_selectioncarets.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/tests/marionette/test_selectioncarets.py 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/tests/marionette/test_selectioncarets.py 2014-11-26 21:46:05.000000000 +0000 @@ -7,6 +7,7 @@ from marionette import Actions from marionette_test import MarionetteTestCase from selection import SelectionManager +from gestures import long_press_without_contextmenu class SelectionCaretsTest(MarionetteTestCase): @@ -48,7 +49,7 @@ # Long press the caret position. Selection carets should appear, and the # first word will be selected. On Windows, those spaces after the word # will also be selected. - self.actions.long_press(el, self._long_press_time, x, y).perform() + long_press_without_contextmenu(self.marionette, el, self._long_press_time, x, y) def _test_long_press_to_select_a_word(self, el, assertFunc): sel = SelectionManager(el) @@ -216,5 +217,4 @@ ######################################################################## def test_content_non_editable_minimum_select_one_character_by_selection(self): self.openTestHtml(enabled=True) - # Currently, selection carets do not show on non-editable elements. - self._test_minimum_select_one_character(self._content, self.assertNotEqual) + self._test_minimum_select_one_character(self._content, self.assertEqual) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/Units.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/Units.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/base/Units.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/base/Units.h 2014-11-26 21:46:04.000000000 +0000 @@ -27,18 +27,7 @@ struct LayerPixel; struct RenderTargetPixel; struct ScreenPixel; -// The layer coordinates of the parent frame. -// This can be arrived at in three ways: -// - Start with the CSS coordinates of the parent frame, multiply by the -// device scale and the cumulative resolution of the parent frame. -// - Start with the CSS coordinates of current frame, multiply by the device -// scale, the cumulative resolution of the current frame, and the scales -// from the CSS and async transforms of the current frame. -// - Start with global screen coordinates and unapply all CSS and async -// transforms from the root down to and including the parent. -// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems -// to get a picture of how the various coordinate systems relate to each other. -struct ParentLayerPixel {}; +struct ParentLayerPixel; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; @@ -247,6 +236,12 @@ return FromUntyped(aRect.ToNearestPixels(aAppUnitsPerDevPixel)); } + static LayoutDeviceIntSize FromAppUnitsRounded(const nsSize& aSize, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntSize( + NSAppUnitsToIntPixels(aSize.width, aAppUnitsPerDevPixel), + NSAppUnitsToIntPixels(aSize.height, aAppUnitsPerDevPixel)); + } + static nsSize ToAppUnits(const LayoutDeviceIntSize& aSize, nscoord aAppUnitsPerDevPixel) { return nsSize(aSize.width * aAppUnitsPerDevPixel, aSize.height * aAppUnitsPerDevPixel); @@ -339,6 +334,24 @@ } }; +/* The layer coordinates of the parent frame. + * This can be arrived at in three ways: + * - Start with the CSS coordinates of the parent frame, multiply by the + * device scale and the cumulative resolution of the parent frame. + * - Start with the CSS coordinates of current frame, multiply by the device + * scale, the cumulative resolution of the current frame, and the scales + * from the CSS and async transforms of the current frame. + * - Start with global screen coordinates and unapply all CSS and async + * transforms from the root down to and including the parent. + * It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems + * to get a picture of how the various coordinate systems relate to each other. + */ +struct ParentLayerPixel { + static nsIntRect ToUntyped(const ParentLayerIntRect& aRect) { + return nsIntRect(aRect.x, aRect.y, aRect.width, aRect.height); + } +}; + // Operators to apply ScaleFactors directly to Coords, Points, Rects, Sizes and Margins template diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/build/nsLayoutModule.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/build/nsLayoutModule.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/build/nsLayoutModule.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/build/nsLayoutModule.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -1129,10 +1129,7 @@ { "@mozilla.org/content/post-content-iterator;1", &kNS_CONTENTITERATOR_CID }, { "@mozilla.org/content/pre-content-iterator;1", &kNS_PRECONTENTITERATOR_CID }, { "@mozilla.org/content/subtree-content-iterator;1", &kNS_SUBTREEITERATOR_CID }, - { "@mozilla.org/content/canvas-rendering-context;1?id=experimental-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID }, -#ifdef MOZ_WEBGL_CONFORMANT { "@mozilla.org/content/canvas-rendering-context;1?id=webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID }, -#endif { NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &kNS_TEXT_ENCODER_CID }, { NS_DOC_ENCODER_CONTRACTID_BASE "application/xml", &kNS_TEXT_ENCODER_CID }, { NS_DOC_ENCODER_CONTRACTID_BASE "application/xhtml+xml", &kNS_TEXT_ENCODER_CID }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/crashtests/1102791.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/crashtests/1102791.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/crashtests/1102791.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/crashtests/1102791.html 2014-11-26 21:46:05.000000000 +0000 @@ -0,0 +1,33 @@ + + + + Testcase for bug 1102791 + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/crashtests/399262.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/crashtests/399262.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/crashtests/399262.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/crashtests/399262.html 2014-11-26 21:46:05.000000000 +0000 @@ -0,0 +1,50 @@ + + + + + + + + +
+ + + + + +
+ +
+ + + + + +
+ + + + + + + +
+ + + + + +
+ +
+ + + + + +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/crashtests/crashtests.list thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/crashtests/crashtests.list --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/crashtests/crashtests.list 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/crashtests/crashtests.list 2014-11-26 21:46:05.000000000 +0000 @@ -33,6 +33,7 @@ load 388374-2.html load 393656-1.xhtml load 393656-2.xhtml +load 399262.html load 402852-1.html load 403148-1.html load 404118-1.html @@ -58,3 +59,4 @@ load 949891.xhtml load 959311.html load 960277-2.html +load 1102791.html diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/nsFileControlFrame.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/nsFileControlFrame.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/nsFileControlFrame.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/nsFileControlFrame.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -187,7 +187,22 @@ } nsCOMPtr dragEvent = do_QueryInterface(aEvent); - if (!dragEvent || !IsValidDropData(dragEvent)) { + if (!dragEvent) { + return NS_OK; + } + + nsCOMPtr dataTransfer; + dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer)); + if (!IsValidDropData(dataTransfer)) { + return NS_OK; + } + + + nsIContent* content = mFrame->GetContent(); + bool supportsMultiple = content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple); + if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) { + dataTransfer->SetDropEffect(NS_LITERAL_STRING("none")); + aEvent->StopPropagation(); return NS_OK; } @@ -203,15 +218,11 @@ aEvent->StopPropagation(); aEvent->PreventDefault(); - nsIContent* content = mFrame->GetContent(); NS_ASSERTION(content, "The frame has no content???"); HTMLInputElement* inputElement = HTMLInputElement::FromContent(content); NS_ASSERTION(inputElement, "No input element for this file upload control frame!"); - nsCOMPtr dataTransfer; - dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer)); - nsCOMPtr fileList; dataTransfer->GetFiles(getter_AddRefs(fileList)); @@ -225,11 +236,9 @@ } /* static */ bool -nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDragEvent* aEvent) +nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer) { - nsCOMPtr domDataTransfer; - aEvent->GetDataTransfer(getter_AddRefs(domDataTransfer)); - nsCOMPtr dataTransfer = do_QueryInterface(domDataTransfer); + nsCOMPtr dataTransfer = do_QueryInterface(aDOMDataTransfer); NS_ENSURE_TRUE(dataTransfer, false); // We only support dropping files onto a file upload control @@ -237,6 +246,23 @@ return types->Contains(NS_LITERAL_STRING("Files")); } +/* static */ bool +nsFileControlFrame::DnDListener::CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer, + bool aSupportsMultiple) +{ + nsCOMPtr dataTransfer = do_QueryInterface(aDOMDataTransfer); + NS_ENSURE_TRUE(dataTransfer, false); + + nsCOMPtr fileList; + dataTransfer->GetFiles(getter_AddRefs(fileList)); + + uint32_t listLength = 0; + if (fileList) { + fileList->GetLength(&listLength); + } + return listLength <= 1 || aSupportsMultiple; +} + nscoord nsFileControlFrame::GetMinISize(nsRenderingContext *aRenderingContext) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/nsFileControlFrame.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/nsFileControlFrame.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/nsFileControlFrame.h 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/nsFileControlFrame.h 2014-11-26 21:46:05.000000000 +0000 @@ -14,7 +14,7 @@ #include "nsCOMPtr.h" class nsTextControlFrame; -class nsIDOMDragEvent; +class nsIDOMDataTransfer; class nsFileControlFrame : public nsBlockFrame, public nsIFormControlFrame, @@ -117,7 +117,8 @@ NS_DECL_NSIDOMEVENTLISTENER - static bool IsValidDropData(nsIDOMDragEvent* aEvent); + static bool IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer); + static bool CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer, bool aSupportsMultiple); }; virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp 2014-11-14 09:37:34.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp 2014-11-26 21:46:05.000000000 +0000 @@ -203,6 +203,11 @@ FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); + // We're always complete and we don't support overflow containers + // so we shouldn't have a next-in-flow ever. + aStatus = NS_FRAME_COMPLETE; + MOZ_ASSERT(!GetNextInFlow()); + NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/429458.xhtml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/429458.xhtml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/429458.xhtml 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/429458.xhtml 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/429960-1.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/429960-1.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/429960-1.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/429960-1.html 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,17 @@ + + + + + + +
examinationx x x x
+ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/429960-2.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/429960-2.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/429960-2.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/429960-2.html 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + + +
examinationx x x x +
+ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/430991.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/430991.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/430991.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/430991.html 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,24 @@ + + + + + + + + +
    +
  • AB + +
  • +
+ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/472957.xhtml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/472957.xhtml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/472957.xhtml 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/472957.xhtml 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/622596.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/622596.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/622596.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/622596.html 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,6 @@ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/crashtests.list thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/crashtests.list --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/crashtests/crashtests.list 2014-11-14 09:37:36.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/crashtests/crashtests.list 2014-11-26 21:46:06.000000000 +0000 @@ -261,12 +261,16 @@ load 426040-1.html load 426272-1.html load 428263-1.html +load 429458.xhtml +load 429960-1.html +load 429960-2.html load 429969-1.html load 429981-1.html load 430332-1.html load 430344-1.html load 430352-1.html load 430744-1.html +load 430991.html load 431260-1.html load 431260-2.html load 435529.html @@ -330,6 +334,7 @@ load 472774-1.html load 472776-1.html load 472950-1.html +load 472957.xhtml load 473278-1.xhtml load 473894-1.html load 476241-1.html @@ -430,6 +435,7 @@ load 619021.html load 621424-1.html load 621841-1.html +load 622596.html load 645072-1.html load 645072-2.html load 646561-1.html @@ -473,7 +479,7 @@ load 737313-3.html load 747688.html load 750066.html -test-pref(font.size.inflation.emPerLine,15) asserts-if(!browserIsRemote,1-100) load font-inflation-762332.html # bug 762332 +pref(dom.meta-viewport.enabled,true) test-pref(font.size.inflation.emPerLine,15) asserts-if(!browserIsRemote,1-100) load font-inflation-762332.html # bug 762332 load 762902.html load 762764-1.html load 765409.html @@ -509,9 +515,9 @@ load 840818.html load 812822-1.html load 812893.html -asserts(1) load 824297-1.html # bug 399262 +load 824297-1.html load 826483-1.html -asserts(1) load 826532-1.html # bug 399262 +load 826532-1.html load 827168-1.html load 836895.html load 837007.xhtml diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp 2014-11-14 09:37:36.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -132,7 +132,8 @@ aConstrainHeight, kidFrame, kidStatus, aOverflowAreas); nsIFrame* nextFrame = kidFrame->GetNextInFlow(); - if (!NS_FRAME_IS_FULLY_COMPLETE(kidStatus)) { + if (!NS_FRAME_IS_FULLY_COMPLETE(kidStatus) && + aDelegatingFrame->IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) { // Need a continuation if (!nextFrame) { nextFrame = diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/nsBlockFrame.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/nsBlockFrame.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/generic/nsBlockFrame.cpp 2014-11-14 09:37:36.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/generic/nsBlockFrame.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -296,7 +296,7 @@ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(PushedFloatProperty) NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OutsideBulletProperty) NS_DECLARE_FRAME_PROPERTY(InsideBulletProperty, nullptr) -NS_DECLARE_FRAME_PROPERTY(BottomEdgeOfChildrenProperty, nullptr) +NS_DECLARE_FRAME_PROPERTY(BlockEndEdgeOfChildrenProperty, nullptr) //---------------------------------------------------------------------- @@ -1048,7 +1048,7 @@ if (GetLogicalSkipSides().BStart()) { blockDirExtras.BStart(wm) = 0; } else { - // Bottom margin never causes us to create continuations, so we + // Block-end margin never causes us to create continuations, so we // don't need to worry about whether it fits in its entirety. blockDirExtras.BStart(wm) += aReflowState.ComputedLogicalMargin().BStart(wm); @@ -1206,11 +1206,11 @@ WritingMode wm = aReflowState.GetWritingMode(); bool havePosition = nsLayoutUtils::GetFirstLinePosition(wm, this, &position); - nscoord lineTop = havePosition ? + nscoord lineBStart = havePosition ? position.mBStart : reflowState->ComputedLogicalBorderPadding().BStart(wm); nsIFrame* bullet = GetOutsideBullet(); - ReflowBullet(bullet, state, metrics, lineTop); + ReflowBullet(bullet, state, metrics, lineBStart); NS_ASSERTION(!BulletIsEmpty() || metrics.BSize(wm) == 0, "empty bullet took up space"); @@ -1225,7 +1225,8 @@ bbox.BStart(wm) = position.mBaseline - metrics.BlockStartAscent(); bullet->SetRect(wm, bbox, metrics.Width()); } - // Otherwise just leave the bullet where it is, up against our top padding. + // Otherwise just leave the bullet where it is, up against our + // block-start padding. } CheckFloats(state); @@ -1369,7 +1370,7 @@ printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d", aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ", aMetrics.ISize(parentWM), aMetrics.BSize(parentWM), - aMetrics.mCarriedOutBottomMargin.get()); + aMetrics.mCarriedOutBEndMargin.get()); if (HasOverflowAreas()) { printf(" overflow-vis={%d,%d,%d,%d}", aMetrics.VisualOverflow().x, @@ -1452,42 +1453,42 @@ aReflowState.ComputedISize()), borderPadding.IEnd(wm)); - // Return bottom margin information + // Return block-end margin information // rbs says he hit this assertion occasionally (see bug 86947), so // just set the margin to zero and we'll figure out why later - //NS_ASSERTION(aMetrics.mCarriedOutBottomMargin.IsZero(), + //NS_ASSERTION(aMetrics.mCarriedOutBEndMargin.IsZero(), // "someone else set the margin"); nscoord nonCarriedOutBDirMargin = 0; if (!aState.GetFlag(BRS_ISBENDMARGINROOT)) { // Apply rule from CSS 2.1 section 8.3.1. If we have some empty - // line with clearance and a non-zero top margin and all + // line with clearance and a non-zero block-start margin and all // subsequent lines are empty, then we do not allow our children's - // carried out bottom margin to be carried out of us and collapse - // with our own bottom margin. + // carried out block-end margin to be carried out of us and collapse + // with our own block-end margin. if (CheckForCollapsedBEndMarginFromClearanceLine()) { // Convert the children's carried out margin to something that // we will include in our height nonCarriedOutBDirMargin = aState.mPrevBEndMargin.get(); aState.mPrevBEndMargin.Zero(); } - aMetrics.mCarriedOutBottomMargin = aState.mPrevBEndMargin; + aMetrics.mCarriedOutBEndMargin = aState.mPrevBEndMargin; } else { - aMetrics.mCarriedOutBottomMargin.Zero(); + aMetrics.mCarriedOutBEndMargin.Zero(); } nscoord blockEndEdgeOfChildren = aState.mBCoord + nonCarriedOutBDirMargin; // Shrink wrap our height around our contents. if (aState.GetFlag(BRS_ISBENDMARGINROOT) || NS_UNCONSTRAINEDSIZE != aReflowState.ComputedBSize()) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. We also do this when + // When we are a block-end-margin root make sure that our last + // childs block-end margin is fully applied. We also do this when // we have a computed height, since in that case the carried out // margin is not going to be applied anywhere, so we should note it // here to be included in the overflow area. // Apply the margin only if there's space for it. if (blockEndEdgeOfChildren < aState.mReflowState.AvailableBSize()) { - // Truncate bottom margin if it doesn't fit to our available height. + // Truncate block-end margin if it doesn't fit to our available BSize. blockEndEdgeOfChildren = std::min(blockEndEdgeOfChildren + aState.mPrevBEndMargin.get(), aState.mReflowState.AvailableBSize()); @@ -1495,7 +1496,7 @@ } if (aState.GetFlag(BRS_FLOAT_MGR)) { // Include the float manager's state to properly account for the - // bottom margin of any floated elements; e.g., inside a table cell. + // block-end margin of any floated elements; e.g., inside a table cell. nscoord floatHeight = aState.ClearFloats(blockEndEdgeOfChildren, NS_STYLE_CLEAR_BOTH, nullptr, nsFloatManager::DONT_CLEAR_PUSHED_FLOATS); @@ -1527,16 +1528,16 @@ // height in the current frame, not whether it's last-in-flow. } - // Don't carry out a bottom margin when our height is fixed. - aMetrics.mCarriedOutBottomMargin.Zero(); + // Don't carry out a block-end margin when our BSize is fixed. + aMetrics.mCarriedOutBEndMargin.Zero(); } else if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) { nscoord contentBSize = blockEndEdgeOfChildren - borderPadding.BStart(wm); nscoord autoBSize = aReflowState.ApplyMinMaxHeight(contentBSize); if (autoBSize != contentBSize) { // Our min-height or max-height made our height change. Don't carry out - // our kids' bottom margins. - aMetrics.mCarriedOutBottomMargin.Zero(); + // our kids' block-end margins. + aMetrics.mCarriedOutBEndMargin.Zero(); } autoBSize += borderPadding.BStart(wm) + borderPadding.BEnd(wm); finalSize.BSize(wm) = autoBSize; @@ -1566,10 +1567,10 @@ FrameProperties properties = Properties(); if (blockEndEdgeOfChildren != finalSize.BSize(wm) - borderPadding.BEnd(wm)) { - properties.Set(BottomEdgeOfChildrenProperty(), + properties.Set(BlockEndEdgeOfChildrenProperty(), NS_INT32_TO_PTR(blockEndEdgeOfChildren)); } else { - properties.Delete(BottomEdgeOfChildrenProperty()); + properties.Delete(BlockEndEdgeOfChildrenProperty()); } aMetrics.SetSize(wm, finalSize); @@ -1583,25 +1584,45 @@ } static void -ConsiderBottomEdgeOfChildren(nscoord aBottomEdgeOfChildren, - nsOverflowAreas& aOverflowAreas) +ConsiderBlockEndEdgeOfChildren(const WritingMode aWritingMode, + nscoord aBEndEdgeOfChildren, + nsOverflowAreas& aOverflowAreas) { - // Factor in the bottom edge of the children. Child frames will be added + // Factor in the block-end edge of the children. Child frames will be added // to the overflow area as we iterate through the lines, but their margins - // won't, so we need to account for bottom margins here. + // won't, so we need to account for block-end margins here. // REVIEW: For now, we do this for both visual and scrollable area, // although when we make scrollable overflow area not be a subset of // visual, we can change this. - NS_FOR_FRAME_OVERFLOW_TYPES(otype) { - nsRect& o = aOverflowAreas.Overflow(otype); - o.height = std::max(o.YMost(), aBottomEdgeOfChildren) - o.y; + // XXX Currently, overflow areas are stored as physical rects, so we have + // to handle writing modes explicitly here. If we change overflow rects + // to be stored logically, this can be simplified again. + if (aWritingMode.IsVertical()) { + if (aWritingMode.IsVerticalLR()) { + NS_FOR_FRAME_OVERFLOW_TYPES(otype) { + nsRect& o = aOverflowAreas.Overflow(otype); + o.width = std::max(o.XMost(), aBEndEdgeOfChildren) - o.x; + } + } else { + NS_FOR_FRAME_OVERFLOW_TYPES(otype) { + nsRect& o = aOverflowAreas.Overflow(otype); + nscoord xmost = o.XMost(); + o.x = std::min(o.x, xmost - aBEndEdgeOfChildren); + o.width = xmost - o.x; + } + } + } else { + NS_FOR_FRAME_OVERFLOW_TYPES(otype) { + nsRect& o = aOverflowAreas.Overflow(otype); + o.height = std::max(o.YMost(), aBEndEdgeOfChildren) - o.y; + } } } void nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds, const nsStyleDisplay* aDisplay, - nscoord aBottomEdgeOfChildren, + nscoord aBEndEdgeOfChildren, nsOverflowAreas& aOverflowAreas) { // Compute the overflow areas of our children @@ -1625,7 +1646,8 @@ areas.UnionAllWith(outsideBullet->GetRect()); } - ConsiderBottomEdgeOfChildren(aBottomEdgeOfChildren, areas); + ConsiderBlockEndEdgeOfChildren(GetWritingMode(), + aBEndEdgeOfChildren, areas); } #ifdef NOISY_COMBINED_AREA @@ -1679,10 +1701,11 @@ kPrincipalList | kFloatList); bool found; - nscoord bottomEdgeOfChildren = NS_PTR_TO_INT32( - Properties().Get(BottomEdgeOfChildrenProperty(), &found)); + nscoord blockEndEdgeOfChildren = NS_PTR_TO_INT32( + Properties().Get(BlockEndEdgeOfChildrenProperty(), &found)); if (found) { - ConsiderBottomEdgeOfChildren(bottomEdgeOfChildren, overflowAreas); + ConsiderBlockEndEdgeOfChildren(GetWritingMode(), + blockEndEdgeOfChildren, overflowAreas); } return FinishAndStoreOverflow(overflowAreas, GetSize()); @@ -2077,7 +2100,7 @@ // Reflow the line if it might not have clearance anymore. if (newBCoord == curBCoord // aState.mBCoord is the clearance point which should be the - // top border-edge of the block frame. If sliding the + // block-start border-edge of the block frame. If sliding the // block by deltaBCoord isn't going to put it in the predicted // position, then we'd better reflow the line. || newBCoord != line->BStart() + deltaBCoord) { @@ -2156,9 +2179,9 @@ } if (needToRecoverState && line->IsDirty()) { - // We need to reconstruct the bottom margin only if we didn't + // We need to reconstruct the block-end margin only if we didn't // reflow the previous line and we do need to reflow (or repair - // the top position of) the next line. + // the block-start position of) the next line. aState.ReconstructMarginBefore(line); } @@ -2227,22 +2250,22 @@ // Test to see whether the margin that should be carried out // to the next line (NL) might have changed. In ReflowBlockFrame // we call nextLine->MarkPreviousMarginDirty if the block's - // actual carried-out bottom margin changed. So here we only + // actual carried-out block-end margin changed. So here we only // need to worry about the following effects: // 1) the line was just created, and it might now be blocking - // a carried-out bottom margin from previous lines that + // a carried-out block-end margin from previous lines that // used to reach NL from reaching NL // 2) the line used to be empty, and is now not empty, - // thus blocking a carried-out bottom margin from previous lines + // thus blocking a carried-out block-end margin from previous lines // that used to reach NL from reaching NL // 3) the line wasn't empty, but now is, so a carried-out - // bottom margin from previous lines that didn't used to reach NL + // block-end margin from previous lines that didn't used to reach NL // now does // 4) the line might have changed in a way that affects NL's // ShouldApplyBStartMargin decision. The three things that matter - // are the line's emptiness, its adjacency to the top of the block, - // and whether it has clearance (the latter only matters if the block - // was and is adjacent to the top and empty). + // are the line's emptiness, its adjacency to the block-start edge of the + // block, and whether it has clearance (the latter only matters if the + // block was and is adjacent to the block-start and empty). // // If the line is empty now, we can't reliably tell if the line was empty // before, so we just assume it was and do nextLine->MarkPreviousMarginDirty. @@ -2956,8 +2979,8 @@ if (!aState.IsAdjacentWithTop() || aChildFrame->StyleBorder()->mBoxDecorationBreak == NS_STYLE_BOX_DECORATION_BREAK_CLONE) { - // If we aren't at the top Y coordinate then something of non-zero - // height must have been placed. Therefore the childs top-margin + // If we aren't at the start block-coordinate then something of non-zero + // height must have been placed. Therefore the childs block-start margin // applies. aState.SetFlag(BRS_APPLYBSTARTMARGIN, true); return true; @@ -2971,11 +2994,11 @@ while (line != aLine) { if (!line->CachedIsEmpty() || line->HasClearance()) { // A line which precedes aLine is non-empty, or has clearance, - // so therefore the top margin applies. + // so therefore the block-start margin applies. aState.SetFlag(BRS_APPLYBSTARTMARGIN, true); return true; } - // No need to apply the top margin if the line has floats. We + // No need to apply the block-start margin if the line has floats. We // should collapse anyway (bug 44419) ++line; aState.SetFlag(BRS_HAVELINEADJACENTTOTOP, true); @@ -2983,7 +3006,7 @@ } // The line being reflowed is "essentially" the first line in the - // block. Therefore its top-margin will be collapsed by the + // block. Therefore its block-start margin will be collapsed by the // generational collapsing logic with its parent (us). return false; } @@ -3015,9 +3038,9 @@ // Clear past floats before the block if the clear style is not none aLine->SetBreakTypeBefore(breakType); - // See if we should apply the top margin. If the block frame being + // See if we should apply the block-start margin. If the block frame being // reflowed is a continuation (non-null prev-in-flow) then we don't - // apply its top margin because it's not significant unless it has + // apply its block-start margin because it's not significant unless it has // 'box-decoration-break:clone'. Otherwise, dig deeper. bool applyBStartMargin = (frame->StyleBorder()->mBoxDecorationBreak == NS_STYLE_BOX_DECORATION_BREAK_CLONE || @@ -3025,7 +3048,7 @@ ShouldApplyBStartMargin(aState, aLine, frame); if (applyBStartMargin) { // The HasClearance setting is only valid if ShouldApplyBStartMargin - // returned false (in which case the top-margin-root set our + // returned false (in which case the block-start margin-root set our // clearance flag). Otherwise clear it now. We'll set it later on // ourselves if necessary. aLine->ClearHasClearance(); @@ -3039,8 +3062,8 @@ replacedBlock = frame; } - // If our top margin was counted as part of some parents top-margin - // collapse and we are being speculatively reflowed assuming this + // If our block-start margin was counted as part of some parent's block-start + // margin collapse, and we are being speculatively reflowed assuming this // frame DID NOT need clearance, then we need to check that // assumption. if (!treatWithClearance && !applyBStartMargin && mightClearFloats && @@ -3080,19 +3103,19 @@ bool mayNeedRetry = false; bool clearedFloats = false; if (applyBStartMargin) { - // Precompute the blocks top margin value so that we can get the + // Precompute the blocks block-start margin value so that we can get the // correct available space (there might be a float that's // already been placed below the aState.mPrevBEndMargin - // Setup a reflowState to get the style computed margin-top + // Setup a reflowState to get the style computed block-start margin // value. We'll use a reason of `resize' so that we don't fudge // any incremental reflow state. // The availSpace here is irrelevant to our needs - all we want - // out if this setup is the margin-top value which doesn't depend + // out if this setup is the block-start margin value which doesn't depend // on the childs available space. - // XXX building a complete nsHTMLReflowState just to get the margin-top - // seems like a waste. And we do this for almost every block! + // XXX building a complete nsHTMLReflowState just to get the block-start + // margin seems like a waste. And we do this for almost every block! WritingMode wm = frame->GetWritingMode(); LogicalSize availSpace = aState.ContentSize(wm); availSpace.BSize(wm) = NS_UNCONSTRAINEDSIZE; @@ -3117,7 +3140,7 @@ if (clearanceFrame) { // Don't allow retries on the second pass. The clearance decisions for the - // blocks whose top-margins collapse with ours are now fixed. + // blocks whose block-start margins collapse with ours are now fixed. mayNeedRetry = false; } @@ -3173,7 +3196,7 @@ // Note that negative clearance is possible clearance = aState.mBCoord - (currentBCoord + bStartMargin); - // Add clearance to our top margin while we compute available + // Add clearance to our block-start margin while we compute available // space for the frame bStartMargin += clearance; @@ -3200,14 +3223,14 @@ // The check for // (!aState.mReflowState.mFlags.mIsTopOfPage || clearedFloats) - // is to some degree out of paranoia: if we reliably eat up top + // is to some degree out of paranoia: if we reliably eat up block-start // margins at the top of the page as we ought to, it wouldn't be // needed. if ((!aState.mReflowState.mFlags.mIsTopOfPage || clearedFloats) && availSpace.BSize(wm) < 0) { // We know already that this child block won't fit on this - // page/column due to the top margin or the clearance. So we need - // to get out of here now. (If we don't, most blocks will handle + // page/column due to the block-start margin or the clearance. So we + // need to get out of here now. (If we don't, most blocks will handle // things fine, and report break-before, but zero-height blocks // won't, and will thus make their parent overly-large and force // *it* to be pushed in its entirety.) @@ -3393,7 +3416,7 @@ } *aKeepReflowGoing = false; - // The bottom margin for a block is only applied on the last + // The block-end margin for a block is only applied on the last // flow block. Since we just continued the child block frame, // we know that line->mFirstChild is not the last flow block // therefore zero out the running margin value. @@ -3494,7 +3517,7 @@ aLine->SetLineIsImpactedByFloat(false); // Setup initial coordinate system for reflowing the inline frames - // into. Apply a previous block frame's bottom margin first. + // into. Apply a previous block frame's block-end margin first. if (ShouldApplyBStartMargin(aState, aLine, aLine->mFirstChild)) { aState.mBCoord += aState.mPrevBEndMargin.get(); } @@ -3505,7 +3528,7 @@ nscoord availableSpaceHeight = 0; do { bool allowPullUp = true; - nsIContent* forceBreakInContent = nullptr; + nsIFrame* forceBreakInFrame = nullptr; int32_t forceBreakOffset = -1; gfxBreakPriority forceBreakPriority = gfxBreakPriority::eNoBreak; do { @@ -3524,8 +3547,8 @@ aState.mReflowState.mFloatManager, &aState.mReflowState, &aLine); lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber); - if (forceBreakInContent) { - lineLayout.ForceBreakAtPosition(forceBreakInContent, forceBreakOffset); + if (forceBreakInFrame) { + lineLayout.ForceBreakAtPosition(forceBreakInFrame, forceBreakOffset); } DoReflowInlineFrames(aState, lineLayout, aLine, floatAvailableSpace, availableSpaceHeight, @@ -3537,13 +3560,14 @@ LINE_REFLOW_REDO_MORE_FLOATS == lineReflowStatus || LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) { if (lineLayout.NeedsBackup()) { - NS_ASSERTION(!forceBreakInContent, "Backing up twice; this should never be necessary"); + NS_ASSERTION(!forceBreakInFrame, "Backing up twice; this should never be necessary"); // If there is no saved break position, then this will set - // set forceBreakInContent to null and we won't back up, which is + // set forceBreakInFrame to null and we won't back up, which is // correct. - forceBreakInContent = lineLayout.GetLastOptionalBreakPosition(&forceBreakOffset, &forceBreakPriority); + forceBreakInFrame = + lineLayout.GetLastOptionalBreakPosition(&forceBreakOffset, &forceBreakPriority); } else { - forceBreakInContent = nullptr; + forceBreakInFrame = nullptr; } // restore the float manager state aState.mReflowState.mFloatManager->PopState(&floatManagerState); @@ -3650,7 +3674,8 @@ if (aFloatAvailableSpace.mHasFloats) { // There is a soft break opportunity at the start of the line, because // we can always move this line down below float(s). - if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, true, gfxBreakPriority::eNormalBreak)) { + if (aLineLayout.NotifyOptionalBreakPosition( + frame, 0, true, gfxBreakPriority::eNormalBreak)) { lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND; } } @@ -3722,11 +3747,12 @@ // We need to try backing up to before a text run int32_t offset; gfxBreakPriority breakPriority; - nsIContent* breakContent = aLineLayout.GetLastOptionalBreakPosition(&offset, &breakPriority); + nsIFrame* breakFrame = + aLineLayout.GetLastOptionalBreakPosition(&offset, &breakPriority); // XXX It's possible, in fact not unusual, for the break opportunity to already // be the end of the line. We should detect that and optimize to not // re-do the line. - if (breakContent) { + if (breakFrame) { // We can back up! lineReflowStatus = LINE_REFLOW_REDO_NO_PULL; } @@ -4283,9 +4309,9 @@ // Inline lines do not have margins themselves; however they are // impacted by prior block margins. If this line ends up having some - // height then we zero out the previous bottom margin value that was + // height then we zero out the previous block-end margin value that was // already applied to the line's starting Y coordinate. Otherwise we - // leave it be so that the previous blocks bottom margin can be + // leave it be so that the previous blocks block-end margin can be // collapsed with a block that follows. nscoord newBCoord; @@ -5895,7 +5921,7 @@ nsCollapsingMargin margin; bool mayNeedRetry = false; floatRS.mDiscoveredClearance = nullptr; - // Only first in flow gets a top margin. + // Only first in flow gets a block-start margin. if (!aFloat->GetPrevInFlow()) { brc.ComputeCollapsedBStartMargin(floatRS, &margin, clearanceFrame, @@ -6561,20 +6587,23 @@ #ifdef DEBUG // The only times a block that is an anonymous box is allowed to have a // first-letter frame are when it's the block inside a non-anonymous cell, - // the block inside a fieldset, a scrolled content block, or a column - // content block. Note that this means that blocks which are the anonymous - // block in {ib} splits do NOT get first-letter frames. Note that - // NS_BLOCK_HAS_FIRST_LETTER_STYLE gets set on all continuations of the - // block. + // the block inside a fieldset, button or column set, or a scrolled content + // block, except for
" "" ) +tagSrcAttrArr=( "src" "src" "data" "poster" ) +numTags=${#tagNameArr[@]} + +# FIRST: Add 'default-preferences' line to the top of our reftest manifest: +echo "default-preferences test-pref(layout.css.object-fit-and-position.enabled,true) +# Tests for 'object-fit' / 'object-position' with a PNG image" \ + >> $REFTEST_LIST_FILE + +for ((i = 0; i < $numObjectFitVals; i++)); do + objectFit=${objectFitArr[$i]} + backgroundSizeEquiv=${backgroundSizeEquivArr[$i]} + + # The reference case for "scale-down" needs an additional style rule, to + # look like "object-fit: scale-down" on small objects. (This is necessary + # because "background-size" doesn't have a value that exactly maps to + # "object-fit: scale-down".) + if [[ $objectFit == "scale-down" ]]; then + scaledownRule=".objectOuter > .small { background-size: contain; }" + scaledownSedCmd="s/REPLACEME_SCALE_DOWN_EXTRA_RULE/$scaledownRule/" + else + # (We're not testing "scale-down" in this generated file, so just delete + # the template's placeholder line for a "scale-down"-specific CSS rule.) + scaledownSedCmd="/REPLACEME_SCALE_DOWN_EXTRA_RULE/d" + fi + + for ((j = 0; j < $numImageFiles; j++)); do + imageFile=${imageFileArr[$j]} + let testNum=$j+1 + testNum="00$testNum" # zero-pad to 3 digits, per w3c convention + + filenameStub="object-fit-$objectFit-$imageFileFormat-$testNum" + + # Generate a reference case: + filenameRef="$filenameStub-ref.html" + echo Generating ${filenameRef}. + cat $TEMPLATE_REFERENCE_FILENAME \ + | sed "s,REPLACEME_IMAGE_FILENAME,$imageFile," \ + | sed "s/REPLACEME_BACKGROUND_SIZE_VAL/$backgroundSizeEquiv/" \ + | sed "$scaledownSedCmd" \ + > $FILE_PATH/$filenameRef; + + # Generate a test for each of our tags: + for ((k = 0; k < $numTags; k++)); do + tagName=${tagNameArr[$k]} + tagLetter=${tagLetterArr[$k]} + tagCloseToken=${tagCloseTokenArr[$k]} + tagSrcAttr=${tagSrcAttrArr[$k]} + + filenameTest="$filenameStub$tagLetter.html" + testTitle="'object-fit: $objectFit' on $tagName element, with a PNG image and with various 'object-position' values" + echo Generating ${filenameTest}. + cat $TEMPLATE_TESTCASE_FILENAME \ + | sed "s,REPLACEME_IMAGE_FILENAME,$imageFile," \ + | sed "s/REPLACEME_TEST_TITLE/$testTitle/" \ + | sed "s,REPLACEME_REFERENCE_FILENAME,$filenameRef," \ + | sed "s/REPLACEME_CONTAINER_TAG/$tagName/" \ + | sed "s,REPLACEME_CONTAINER_CLOSETAG,$tagCloseToken," \ + | sed "s/REPLACEME_SRC_ATTR/$tagSrcAttr/" \ + | sed "s/REPLACEME_OBJECT_FIT_VAL/$objectFit/" \ + > $FILE_PATH/$filenameTest + + echo "== $filenameTest $filenameRef" \ + >> $REFTEST_LIST_FILE + done + done +done diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-svg-tests.sh thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-svg-tests.sh --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-svg-tests.sh 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-svg-tests.sh 2014-11-26 21:45:51.000000000 +0000 @@ -0,0 +1,116 @@ +#!/bin/bash +# +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ +# +# This is a script that I used to generate a suite of tests for the CSS +# properties "object-fit" and "object-position", using a template testcase +# file and reference case file. +# +# The reference case uses the "background-size" & "background-position" +# equivalent of the tested "object-fit" / "object-position" values. +# (One exception: since there is no "background-size" equivalent of +# "object-fit: scale-down", we add an extra CSS rule for the "scale-down" +# reference cases -- see REPLACEME_SCALE_DOWN_EXTRA_RULE below.) + +FILE_PATH="./" +REFTEST_LIST_FILE="$FILE_PATH/reftest.list" + +TEMPLATE_TESTCASE_FILENAME=$FILE_PATH/support/template-object-fit-test.html +TEMPLATE_REFERENCE_FILENAME=$FILE_PATH/support/template-object-fit-ref.html + +imageFileFormat="svg" + +# Array of image files to use for testing: +imageFileArr=("support/colors-16x8.svg" + "support/colors-8x16.svg" + "support/colors-16x8-noSize.svg" + "support/colors-8x16-noSize.svg" + "support/colors-16x8-parDefault.svg" + "support/colors-8x16-parDefault.svg") +numImageFiles=${#imageFileArr[@]} + +# Array of "object-fit" values, & of corresponding "background-size" values. +# (Note: background-size has no equivalent for "object-fit: scale-down". We use +# "auto auto" here, which is equivalent *some* of the time; and for the cases +# where it's *not* equivalent, we use an extra CSS rule in the reference case. +# See REPLACEME_SCALE_DOWN_EXTRA_RULE below.) +objectFitArr=( "fill" "contain" "cover" "none" "scale-down" ) +backgroundSizeEquivArr=( "100% 100%" "contain" "cover" "auto auto" "auto auto" ) +numObjectFitVals=${#objectFitArr[@]} + +# Array of tag-names for elements that we'd like to test: +# (Also: array of a single-letter abbreviation for each element, an array of +# the close tag for each element -- if a close tag is needed -- and an array +# indicating the attribute that each element uses to specify its image source.) +tagNameArr=( "embed" "img" "object" "video" ) +tagLetterArr=( "e" "i" "o" "p" ) +tagCloseTokenArr=( "" "" "" "" ) +tagSrcAttrArr=( "src" "src" "data" "poster" ) +numTags=${#tagNameArr[@]} + +# FIRST: Add blank line & descriptive comment to reftest manifest: +echo " +# Tests for 'object-fit' / 'object-position' with an SVG image" \ + >> $REFTEST_LIST_FILE + +for ((i = 0; i < $numObjectFitVals; i++)); do + objectFit=${objectFitArr[$i]} + backgroundSizeEquiv=${backgroundSizeEquivArr[$i]} + + # The reference case for "scale-down" needs an additional style rule, to + # look like "object-fit: scale-down" on small objects. (This is necessary + # because "background-size" doesn't have a value that exactly maps to + # "object-fit: scale-down".) + if [[ $objectFit == "scale-down" ]]; then + scaledownRule=".objectOuter > .small { background-size: contain; }" + scaledownSedCmd="s/REPLACEME_SCALE_DOWN_EXTRA_RULE/$scaledownRule/" + else + # (We're not testing "scale-down" in this generated file, so just delete + # the template's placeholder line for a "scale-down"-specific CSS rule.) + scaledownSedCmd="/REPLACEME_SCALE_DOWN_EXTRA_RULE/d" + fi + + for ((j = 0; j < $numImageFiles; j++)); do + imageFile=${imageFileArr[$j]} + let testNum=$j+1 + testNum="00$testNum" # zero-pad to 3 digits, per w3c convention + + filenameStub="object-fit-$objectFit-$imageFileFormat-$testNum" + + # Generate a reference case: + filenameRef="$filenameStub-ref.html" + echo Generating ${filenameRef}. + cat $TEMPLATE_REFERENCE_FILENAME \ + | sed "s,REPLACEME_IMAGE_FILENAME,$imageFile," \ + | sed "s/REPLACEME_BACKGROUND_SIZE_VAL/$backgroundSizeEquiv/" \ + | sed "$scaledownSedCmd" \ + | sed "/image-rendering:/d" \ + > $FILE_PATH/$filenameRef; + + # Generate a test for each of our tags: + for ((k = 0; k < $numTags; k++)); do + tagName=${tagNameArr[$k]} + tagLetter=${tagLetterArr[$k]} + tagCloseToken=${tagCloseTokenArr[$k]} + tagSrcAttr=${tagSrcAttrArr[$k]} + + filenameTest="$filenameStub$tagLetter.html" + testTitle="'object-fit: $objectFit' on $tagName element, with a SVG image and with various 'object-position' values" + echo Generating ${filenameTest}. + cat $TEMPLATE_TESTCASE_FILENAME \ + | sed "s,REPLACEME_IMAGE_FILENAME,$imageFile," \ + | sed "s/REPLACEME_TEST_TITLE/$testTitle/" \ + | sed "s,REPLACEME_REFERENCE_FILENAME,$filenameRef," \ + | sed "s/REPLACEME_CONTAINER_TAG/$tagName/" \ + | sed "s,REPLACEME_CONTAINER_CLOSETAG,$tagCloseToken," \ + | sed "s/REPLACEME_SRC_ATTR/$tagSrcAttr/" \ + | sed "s/REPLACEME_OBJECT_FIT_VAL/$objectFit/" \ + | sed "/image-rendering:/d" \ + > $FILE_PATH/$filenameTest + + echo "== $filenameTest $filenameRef" \ + >> $REFTEST_LIST_FILE + done + done +done diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-ref.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-ref.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-ref.html 2014-11-26 21:45:51.000000000 +0000 @@ -0,0 +1,78 @@ + + + + + + CSS Reftest Reference + + + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-test.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-test.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-test.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/images3/support/template-object-fit-test.html 2014-11-26 21:45:51.000000000 +0000 @@ -0,0 +1,77 @@ + + + + + + CSS Test: REPLACEME_TEST_TITLE + + + + + + + + + + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG +
+ + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG +
+ + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG + REPLACEME_CONTAINER_CLOSETAG +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/reftest.list thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/reftest.list --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/w3c-css/submitted/reftest.list 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/w3c-css/submitted/reftest.list 2014-11-26 21:45:51.000000000 +0000 @@ -26,7 +26,7 @@ # include fonts3/reftest.list # Image Values and Replaced Content Level 3 -# include images3/reftest.list +include images3/reftest.list # Media Queries Level 3 # include mediaqueries3/reftest.list Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/webm-video/colors-16x8.png and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/webm-video/colors-16x8.png differ Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/webm-video/colors-16x8.webm and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/webm-video/colors-16x8.webm differ Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/webm-video/colors-8x16.png and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/webm-video/colors-8x16.png differ Binary files /tmp/vyS4zUifeA/thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/webm-video/colors-8x16.webm and /tmp/TR1sH7LEm2/thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/webm-video/colors-8x16.webm differ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/webm-video/generate-object-fit-video-tests.sh thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/webm-video/generate-object-fit-video-tests.sh --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/layout/reftests/webm-video/generate-object-fit-video-tests.sh 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/layout/reftests/webm-video/generate-object-fit-video-tests.sh 2014-11-26 21:45:51.000000000 +0000 @@ -0,0 +1,87 @@ +#!/bin/bash +# +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ +# +# Script to generate
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -2,6 +2,7 @@ touch-action: parent > child: pan-x > child: pan-y + @@ -18,7 +19,7 @@

Pointer Events touch-action attribute support

-

Test Description: Try to scroll text DOWN. Wait for description update. Expected: no panning/zooming/etc.

+

Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning/zooming/etc.

Note: this test is for touch-devices only

@@ -78,14 +79,8 @@
+ @@ -15,7 +16,7 @@

Pointer Events touch-action attribute support

-

Test Description: Try to scroll text DOWN. Wait for description update. Expected: no panning

+

Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning

Note: this test is for touch-devices only

@@ -73,44 +74,28 @@

Lorem ipsum dolor sit amet...

+

touch-action: none

-

The following pointer types were detected: .

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -2,6 +2,7 @@ touch-action: none + @@ -17,7 +18,7 @@

Pointer Events touch-action attribute support

-

Test Description: Try to scroll text DOWN. Wait for description update. Expected: no panning/zooming/etc.

+

Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning/zooming/etc.

Note: this test is for touch-devices only

@@ -73,35 +74,27 @@

Lorem ipsum dolor sit amet...

Lorem ipsum dolor sit amet...

+ @@ -17,7 +18,7 @@

Pointer Events touch-action attribute support

-

Test Description: Try to scroll text DOWN. Wait for description update. Expected: only pans in x direction.

+

Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in x direction.

Note: this test is for touch-devices only

@@ -73,54 +74,26 @@

Lorem ipsum dolor sit amet...

Lorem ipsum dolor sit amet...

+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -2,6 +2,7 @@ touch-action: parent > child: pan-x pan-y > child: pan-y + @@ -18,7 +19,7 @@

Pointer Events touch-action attribute support

-

Test Description: Try to scroll text DOWN. Wait for description update. Expected: no panning/zooming/etc.

+

Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in y direction.

Note: this test is for touch-devices only

@@ -76,59 +77,34 @@
+

behaviour: pan-y

The following pointer types were detected: .

-

Would you like to run the tests again with a different pointer type?

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -2,6 +2,7 @@ touch-action: pan-y + @@ -17,7 +18,7 @@

Pointer Events touch-action attribute support

-

Test Description: Try to scroll text DOWN. Wait for description update. Expected: only pans in y direction.

+

Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in y direction.

Note: this test is for touch-devices only

@@ -73,54 +74,26 @@

Lorem ipsum dolor sit amet...

Lorem ipsum dolor sit amet...

+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -60,7 +60,6 @@ yScr0 = target0.scrollTop; on_event(btnComplete, 'click', function(event) { - detected_pointertypes[event.pointerType] = true; test_touchaction_span.step(function() { assert_not_equals(target0.scrollLeft, 0, "span scroll x offset should not be 0 in the end of the test"); assert_not_equals(target0.scrollTop, 0, "span scroll y offset should not be 0 in the end of the test"); @@ -70,6 +69,10 @@ updateDescriptionComplete(); }); + on_event(btnComplete, 'pointerdown', function(event) { + detected_pointertypes[event.pointerType] = true; + }); + on_event(target0, 'scroll', function(event) { if(isFirstPart) { xScr1 = target0.scrollLeft; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -50,8 +50,7 @@ xScr0 = target0.scrollLeft; yScr0 = target0.scrollTop; - on_event(btnComplete, 'pointerdown', function(event) { - detected_pointertypes[event.pointerType] = true; + on_event(btnComplete, 'click', function(event) { test_touchaction_svg.step(function() { assert_equals(target0.scrollLeft, 0, "SVG scroll x offset should be 0 in the end of the test"); assert_equals(target0.scrollTop, 0, "SVG scroll y offset should be 0 in the end of the test"); @@ -60,6 +59,10 @@ updateDescriptionComplete(); }); + on_event(btnComplete, 'pointerdown', function(event) { + detected_pointertypes[event.pointerType] = true; + }); + on_event(target0, 'scroll', function(event) { if(isFirstPart) { xScr1 = target0.scrollLeft; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -72,7 +72,6 @@ yScr0 = target0.scrollTop; on_event(btnComplete, 'click', function(event) { - detected_pointertypes[event.pointerType] = true; test_touchaction_cell.step(function() { assert_equals(target0.scrollLeft, 0, "table scroll x offset should be 0 in the end of the test"); assert_equals(target0.scrollTop, 0, "table scroll y offset should be 0 in the end of the test"); @@ -82,6 +81,10 @@ updateDescriptionComplete(); }); + on_event(btnComplete, 'pointerdown', function(event) { + detected_pointertypes[event.pointerType] = true; + }); + on_event(target0, 'scroll', function(event) { if(isFirstPart) { xScr1 = target0.scrollLeft; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,5 +1,5 @@ def main(request, response): - response.headers.extend([('Transfer-Encoding', 'chunked'), + response.headers.update([('Transfer-Encoding', 'chunked'), ('Content-Type', 'text/html'), ('Connection', 'keep-alive')]) response.write_status_headers() diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resources/idlharness.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resources/idlharness.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resources/idlharness.js 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resources/idlharness.js 2014-11-26 21:45:59.000000000 +0000 @@ -426,6 +426,9 @@ return; case "DOMString": + case "ByteString": + case "USVString": + // TODO: https://github.com/w3c/testharness.js/issues/92 assert_equals(typeof value, "string"); return; @@ -1026,15 +1029,15 @@ if (!this.is_callback()) { test(function() { - // This function tests WebIDL as of 2013-08-25. - // http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call + // This function tests WebIDL as of 2014-10-25. + // https://heycam.github.io/webidl/#es-interface-call assert_own_property(window, this.name, "window does not have own property " + format_value(this.name)); // "Interface objects for non-callback interfaces MUST have a // property named “length” with attributes { [[Writable]]: false, - // [[Enumerable]]: false, [[Configurable]]: false } whose value is + // [[Enumerable]]: false, [[Configurable]]: true } whose value is // a Number." assert_own_property(window[this.name], "length"); var desc = Object.getOwnPropertyDescriptor(window[this.name], "length"); @@ -1042,7 +1045,7 @@ assert_false("set" in desc, this.name + ".length has setter"); assert_false(desc.writable, this.name + ".length is writable"); assert_false(desc.enumerable, this.name + ".length is enumerable"); - assert_false(desc.configurable, this.name + ".length is configurable"); + assert_true(desc.configurable, this.name + ".length is not configurable"); var constructors = this.extAttrs .filter(function(attr) { return attr.name == "Constructor"; }); @@ -1266,10 +1269,14 @@ "The prototype object must have a property " + format_value(member.name)); - // TODO: Needs to test for LenientThis. - assert_throws(new TypeError(), function() { - window[this.name].prototype[member.name]; - }.bind(this), "getting property on prototype object must throw TypeError"); + if (!member.has_extended_attribute("LenientThis")) { + assert_throws(new TypeError(), function() { + window[this.name].prototype[member.name]; + }.bind(this), "getting property on prototype object must throw TypeError"); + } else { + assert_equals(window[this.name].prototype[member.name], undefined, + "getting property on prototype object must return undefined"); + } do_interface_attribute_asserts(window[this.name].prototype, member); } }.bind(this), this.name + " interface: attribute " + member.name); @@ -1705,11 +1712,14 @@ // value 0." assert_equals(typeof desc.get, "function", "getter must be Function"); assert_equals(desc.get.length, 0, "getter length must be 0"); - // TODO: Account for LenientThis - assert_throws(new TypeError(), function() - { - desc.get.call({}); - }.bind(this), "calling getter on wrong object type must throw TypeError"); + if (!member.has_extended_attribute("LenientThis")) { + assert_throws(new TypeError(), function() { + desc.get.call({}); + }.bind(this), "calling getter on wrong object type must throw TypeError"); + } else { + assert_equals(desc.get.call({}), undefined, + "calling getter on wrong object type must return undefined"); + } // TODO: Test calling setter on the interface prototype (should throw // TypeError in most cases). @@ -1731,6 +1741,14 @@ { assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes"); assert_equals(desc.set.length, 1, "setter length must be 1"); + if (!member.has_extended_attribute("LenientThis")) { + assert_throws(new TypeError(), function() { + desc.set.call({}); + }.bind(this), "calling setter on wrong object type must throw TypeError"); + } else { + assert_equals(desc.set.call({}), undefined, + "calling setter on wrong object type must return undefined"); + } } } //@} @@ -1783,6 +1801,8 @@ return 7; case "DOMString": + case "ByteString": + case "USVString": return "foo"; case "object": diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resources/readme.md thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resources/readme.md --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resources/readme.md 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resources/readme.md 2014-11-26 21:45:59.000000000 +0000 @@ -16,7 +16,8 @@ ## Full documentation ## -Full documentation of the API is kept in the source of testharness.js. +Full user documentation for the API is in the +[docs/api.md](https://github.com/w3c/testharness.js/blob/master/docs/api.md) file. You can also read a tutorial on [Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html). diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resources/testharness.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resources/testharness.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resources/testharness.js 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resources/testharness.js 2014-11-26 21:45:59.000000000 +0000 @@ -10,7 +10,7 @@ [3] http://www.w3.org/2004/10/27-testcases */ -/* Documentation is in docs/testharness.md */ +/* Documentation is in docs/api.md */ (function () { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resource-timing/test_resource_timing.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resource-timing/test_resource_timing.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/resource-timing/test_resource_timing.js 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/resource-timing/test_resource_timing.js 2014-11-26 21:45:59.000000000 +0000 @@ -115,9 +115,10 @@ function inner() { for(var i=0; i 0) { + setTimeout(function() { + resource_load(expected_entry); + }, 200); return; } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,87 @@ + + +Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 + + + + + + + + +
This test requires JavaScript.
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/Element-matches.js 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * Check that the matches() method exists on the given Node + */ +function interfaceCheckMatches(type, obj) { + if (obj.nodeType === obj.ELEMENT_NODE) { + test(function() { + assert_idl_attribute(obj, "matches", type + " supports matches"); + }, type + " supports matches") + } +} + +function runSpecialMatchesTests(type, element) { + test(function() { // 1 + if (element.tagName.toLowerCase() === "null") { + assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); + } else { + assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); + } + }, type + ".matches(null)") + + test(function() { // 2 + if (element.tagName.toLowerCase() === "undefined") { + assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); + } else { + assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); + } + }, type + ".matches(undefined)") + + test(function() { // 3 + assert_throws(TypeError(), function() { + element.matches(); + }, "This should throw a TypeError.") + }, type + ".matches no parameter") +} + +/* + * Execute queries with the specified invalid selectors for matches() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ +function runInvalidSelectorTestMatches(type, root, selectors) { + if (root.nodeType === root.ELEMENT_NODE) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + test(function() { + assert_throws("SyntaxError", function() { + root.matches(q) + }) + }, type + ".matches: " + n + ": " + q); + } + } +} + +function runMatchesTest(type, root, selectors, docType) { + var nodeType = getNodeType(root); + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + var u = s["unexpected"]; + + var ctx = s["ctx"]; + var ref = s["ref"]; + + if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) + && (s["testType"] & TEST_MATCH) ) { + + if (ctx && !ref) { + test(function() { + var j, element, refNode; + for (j = 0; j < e.length; j++) { + element = root.querySelector("#" + e[j]); + refNode = root.querySelector(ctx); + assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + refNode = root.querySelector(ctx); + assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element.matches: " + n + " (with refNode Element): " + q); + } + + if (ref) { + test(function() { + var j, element, refNodes; + for (j = 0; j < e.length; j++) { + element = root.querySelector("#" + e[j]); + refNodes = root.querySelectorAll(ref); + assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + refNodes = root.querySelectorAll(ref); + assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element.matches: " + n + " (with refNodes NodeList): " + q); + } + + if (!ctx && !ref) { + test(function() { + for (var j = 0; j < e.length; j++) { + var element = root.querySelector("#" + e[j]); + assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element.matches: " + n + " (with no refNodes): " + q); + } + } + } +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-baseline.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-baseline.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-baseline.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-baseline.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ - - -Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 - - - - - - - -
This test requires JavaScript.
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-lib.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-lib.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-lib.js 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/level2-lib.js 2014-11-26 21:45:59.000000000 +0000 @@ -47,403 +47,14 @@ parent.appendChild(noNS); } -/* - * Check that the find, findAll and matches() methods exist on the given Node - */ -function interfaceCheck(type, obj) { - test(function() { - var q = typeof obj.find === "function"; - assert_true(q, type + " supports find."); - }, type + " supports find") - - test(function() { - var qa = typeof obj.findAll === "function"; - assert_true( qa, type + " supports findAll."); - }, type + " supports findAll") - - if (obj.nodeType === obj.ELEMENT_NODE) { - test(function() { - assert_idl_attribute(obj, "matches", type + " supports matches"); - }, type + " supports matches") - } -} - -/* - * Verify that the NodeList returned by findAll is static and and that a new list is created after - * each call. A static list should not be affected by subsequent changes to the DOM. - */ -function verifyStaticList(type, root) { - var pre, post, preLength; - - test(function() { - pre = root.findAll("div"); - preLength = pre.length; - - var div = doc.createElement("div"); - (root.body || root).appendChild(div); - - assert_equals(pre.length, preLength, "The length of the NodeList should not change.") - }, type + ": static NodeList") - - test(function() { - post = root.findAll("div"), - assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.") - }, type + ": new NodeList") -} - -/* - * Verify handling of special values for the selector parameter, including stringification of - * null and undefined, and the handling of the empty string. - */ -function runSpecialSelectorTests(type, root) { - test(function() { // 1 - assert_equals(root.findAll(null).length, 1, "This should find one element with the tag name 'NULL'."); - }, type + ".findAll null") - - test(function() { // 2 - assert_equals(root.findAll(undefined).length, 1, "This should find one elements with the tag name 'UNDEFINED'."); - }, type + ".findAll undefined") - - test(function() { // 3 - assert_throws(TypeError(), function() { - root.findAll(); - }, "This should throw a TypeError.") - }, type + ".findAll no parameter") - - test(function() { // 4 - var elm = root.find(null) - assert_not_equals(elm, null, "This should find an element."); - assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.") - }, type + ".find null") - - test(function() { // 5 - var elm = root.find(undefined) - assert_not_equals(elm, undefined, "This should find an element."); - assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.") - }, type + ".find undefined") - - test(function() { // 6 - assert_throws(TypeError(), function() { - root.find(); - }, "This should throw a TypeError.") - }, type + ".find no parameter.") - - test(function() { // 7 - result = root.findAll("*"); - var i = 0; - traverse(root, function(elem) { - if (elem !== root) { - assert_equals(elem, result[i++], "The result in index " + i + " should be in tree order.") - } - }) - }, type + ".findAll tree order"); -} - -function runSpecialMatchesTests(type, element) { - test(function() { // 1 - if (element.tagName.toLowerCase() === "null") { - assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); - } else { - assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); - } - }, type + ".matches(null)") - - test(function() { // 2 - if (element.tagName.toLowerCase() === "undefined") { - assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); - } else { - assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); - } - }, type + ".matches(undefined)") - - test(function() { // 3 - assert_throws(TypeError(), function() { - element.matches(); - }, "This should throw a TypeError.") - }, type + ".matches no parameter") -} - -/* - * Execute queries with the specified valid selectors for both find() and findAll() - * Only run these tests when results are expected. Don't run for syntax error tests. - * - * Where testType is TEST_FIND_BASELINE or TEST_FIND_ADDITIONAL: - * - * context.findAll(selector, refNodes) - * context.findAll(selector) // Only if refNodes is not specified - * root.findAll(selector, context) // Only if refNodes is not specified - * root.findAll(selector, refNodes) // Only if context is not specified - * root.findAll(selector) // Only if neither context nor refNodes is specified - * - * Where testType is TEST_QSA_BASELINE or TEST_QSA_ADDITIONAL - * - * context.querySelectorAll(selector) // Only if refNodes is not specified - * root.querySelectorAll(selector) // Only if neither context nor refNodes is specified - * - * Equivalent tests will be run for .find() as well. - * Note: Do not specify a testType of TEST_QSA_* where either implied :scope or explicit refNodes - * are required. - */ -function runValidSelectorTest(type, root, selectors, testType, docType) { - var nodeType = getNodeType(root); - - for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s["name"]; - var q = s["selector"]; - var e = s["expect"]; - - var ctx = s["ctx"]; - var ref = s["ref"]; - - if (!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) { - //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) - var foundall, found, context, refNodes, refArray; - - if (s["testType"] & testType & (TEST_FIND)) { - - - /* - * If ctx and ref are specified: - * context.findAll(selector, refNodes) - * context.find(selector, refNodes) - */ - if (ctx && ref) { - context = root.querySelector(ctx); - refNodes = root.querySelectorAll(ref); - refArray = Array.prototype.slice.call(refNodes, 0); - - test(function() { - foundall = context.findAll(q, refNodes); - verifyNodeList(foundall, expect); - }, type + " [Context Element].findAll: " + n + " (with refNodes NodeList): " + q); - - test(function() { - foundall = context.findAll(q, refArray); - verifyNodeList(foundall, expect); - }, type + " [Context Element].findAll: " + n + " (with refNodes Array): " + q); - - test(function() { - found = context.find(q, refNodes); - verifyElement(found, foundall, expect) - }, type + " [Context Element].find: " + n + " (with refNodes NodeList): " + q); - - test(function() { - found = context.find(q, refArray); - verifyElement(found, foundall, expect) - }, type + " [Context Element].find: " + n + " (with refNodes Array): " + q); - } - - - /* - * If ctx is specified, ref is not: - * context.findAll(selector) - * context.find(selector) - * root.findAll(selector, context) - * root.find(selector, context) - */ - if (ctx && !ref) { - context = root.querySelector(ctx); - - test(function() { - foundall = context.findAll(q); - verifyNodeList(foundall, expect); - }, type + " [Context Element].findAll: " + n + " (with no refNodes): " + q); - - test(function() { - found = context.find(q); - verifyElement(found, foundall, expect) - }, type + " [Context Element].find: " + n + " (with no refNodes): " + q); - - test(function() { - foundall = root.findAll(q, context); - verifyNodeList(foundall, expect); - }, type + " [Root Node].findAll: " + n + " (with refNode Element): " + q); - - test(function() { - foundall = root.find(q, context); - verifyElement(found, foundall, expect); - }, type + " [Root Node].find: " + n + " (with refNode Element): " + q); - } - - /* - * If ref is specified, ctx is not: - * root.findAll(selector, refNodes) - * root.find(selector, refNodes) - */ - if (!ctx && ref) { - refNodes = root.querySelectorAll(ref); - refArray = Array.prototype.slice.call(refNodes, 0); - - test(function() { - foundall = root.findAll(q, refNodes); - verifyNodeList(foundall, expect); - }, type + " [Root Node].findAll: " + n + " (with refNodes NodeList): " + q); - - test(function() { - foundall = root.findAll(q, refArray); - verifyNodeList(foundall, expect); - }, type + " [Root Node].findAll: " + n + " (with refNodes Array): " + q); - - test(function() { - found = root.find(q, refNodes); - verifyElement(found, foundall, expect); - }, type + " [Root Node].find: " + n + " (with refNodes NodeList): " + q); - - test(function() { - found = root.find(q, refArray); - verifyElement(found, foundall, expect); - }, type + " [Root Node].find: " + n + " (with refNodes Array): " + q); - } - - /* - * If neither ctx nor ref is specified: - * root.findAll(selector) - * root.find(selector) - */ - if (!ctx && !ref) { - test(function() { - foundall = root.findAll(q); - verifyNodeList(foundall, expect); - }, type + ".findAll: " + n + " (with no refNodes): " + q); - - test(function() { - found = root.find(q); - verifyElement(found, foundall, expect); - }, type + ".find: " + n + " (with no refNodes): " + q); - } - } - - if (s["testType"] & testType & (TEST_QSA)) { - if (ctx && !ref) { - // context.querySelectorAll(selector) // Only if refNodes is not specified - } - - if (!ctx && !ref) { - // root.querySelectorAll(selector) // Only if neither context nor refNodes is specified - } - } - } else { - //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) - } - } -} - -/* - * Execute queries with the specified invalid selectors for both find() and findAll() - * Only run these tests when errors are expected. Don't run for valid selector tests. - */ -function runInvalidSelectorTest(type, root, selectors) { - for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s["name"]; - var q = s["selector"]; - - test(function() { - assert_throws("SyntaxError", function() { - root.find(q) - }) - }, type + ".find: " + n + ": " + q); - - test(function() { - assert_throws("SyntaxError", function() { - root.findAll(q) - }) - }, type + ".findAll: " + n + ": " + q); - - if (root.nodeType === root.ELEMENT_NODE) { - test(function() { - assert_throws("SyntaxError", function() { - root.matches(q) - }) - }, type + ".matches: " + n + ": " + q); - } - } -} - -function runMatchesTest(type, root, selectors, testType, docType) { - var nodeType = getNodeType(root); - - for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s["name"]; - var q = s["selector"]; - var e = s["expect"]; - var u = s["unexpected"]; - - var ctx = s["ctx"]; - var ref = s["ref"]; - - if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) - && (s["testType"] & testType & (TEST_MATCH)) ) { - - if (ctx && !ref) { - test(function() { - var j, element, refNode; - for (j = 0; j < e.length; j++) { - element = root.querySelector("#" + e[j]); - refNode = root.querySelector(ctx); - assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.") - } - - if (u) { - for (j = 0; j < u.length; j++) { - element = root.querySelector("#" + u[j]); - refNode = root.querySelector(ctx); - assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.") - } - } - }, type + " Element.matches: " + n + " (with refNode Element): " + q); - } - - if (ref) { - test(function() { - var j, element, refNodes; - for (j = 0; j < e.length; j++) { - element = root.querySelector("#" + e[j]); - refNodes = root.querySelectorAll(ref); - assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.") - } - - if (u) { - for (j = 0; j < u.length; j++) { - element = root.querySelector("#" + u[j]); - refNodes = root.querySelectorAll(ref); - assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.") - } - } - }, type + " Element.matches: " + n + " (with refNodes NodeList): " + q); - } - - if (!ctx && !ref) { - test(function() { - for (var j = 0; j < e.length; j++) { - var element = root.querySelector("#" + e[j]); - assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.") - } - - if (u) { - for (j = 0; j < u.length; j++) { - element = root.querySelector("#" + u[j]); - assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.") - } - } - }, type + " Element.matches: " + n + " (with no refNodes): " + q); - } - } - } -} - - function traverse(elem, fn) { if (elem.nodeType === elem.ELEMENT_NODE) { fn(elem); - - elem = elem.firstChild; - while (elem) { - traverse(elem, fn); - elem = elem.nextSibling; - } + } + elem = elem.firstChild; + while (elem) { + traverse(elem, fn); + elem = elem.nextSibling; } } @@ -460,25 +71,3 @@ return "unknown"; // This should never happen. } } - -function verifyNodeList(resultAll, expect) { - assert_not_equals(resultAll, null, "The method should not return null."); - assert_equals(resultAll.length, e.length, "The method should return the expected number of matches."); - - for (var i = 0; i < e.length; i++) { - assert_not_equals(resultAll[i], null, "The item in index " + i + " should not be null.") - assert_equals(resultAll[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID."); - assert_false(resultAll[i].hasAttribute("data-clone"), "This should not be a cloned element."); - } -} - -function verifyElement(result, resultAll, expect) { - if (expect.length > 0) { - assert_not_equals(result, null, "The method should return a match.") - assert_equals(found.getAttribute("id"), e[0], "The method should return the first match."); - assert_equals(result, resultAll[0], "The result should match the first item from querySelectorAll."); - assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element."); - } else { - assert_equals(result, null, "The method should not match anything."); - } -} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,89 @@ + + +Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 + + + + + + + + +
This test requires JavaScript.
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-find-findAll.js 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,278 @@ +/* + * Check that the find and findAll methods exist on the given Node + */ +function interfaceCheckFind(type, obj) { + test(function() { + var q = typeof obj.find === "function"; + assert_true(q, type + " supports find."); + }, type + " supports find") + + test(function() { + var qa = typeof obj.findAll === "function"; + assert_true( qa, type + " supports findAll."); + }, type + " supports findAll") +} + +/* + * Verify that the NodeList returned by findAll is static and and that a new list is created after + * each call. A static list should not be affected by subsequent changes to the DOM. + */ +function verifyStaticList(type, root) { + var pre, post, preLength; + + test(function() { + pre = root.findAll("div"); + preLength = pre.length; + + var div = doc.createElement("div"); + (root.body || root).appendChild(div); + + assert_equals(pre.length, preLength, "The length of the NodeList should not change.") + }, type + ": static NodeList") + + test(function() { + post = root.findAll("div"), + assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.") + }, type + ": new NodeList") +} + +/* + * Verify handling of special values for the selector parameter, including stringification of + * null and undefined, and the handling of the empty string. + */ +function runSpecialSelectorTests(type, root) { + test(function() { // 1 + assert_equals(root.findAll(null).length, 1, "This should find one element with the tag name 'NULL'."); + }, type + ".findAll null") + + test(function() { // 2 + assert_equals(root.findAll(undefined).length, 1, "This should find one elements with the tag name 'UNDEFINED'."); + }, type + ".findAll undefined") + + test(function() { // 3 + assert_throws(TypeError(), function() { + root.findAll(); + }, "This should throw a TypeError.") + }, type + ".findAll no parameter") + + test(function() { // 4 + var elm = root.find(null) + assert_not_equals(elm, null, "This should find an element."); + assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.") + }, type + ".find null") + + test(function() { // 5 + var elm = root.find(undefined) + assert_not_equals(elm, undefined, "This should find an element."); + assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.") + }, type + ".find undefined") + + test(function() { // 6 + assert_throws(TypeError(), function() { + root.find(); + }, "This should throw a TypeError.") + }, type + ".find no parameter.") + + test(function() { // 7 + result = root.findAll("*"); + var i = 0; + traverse(root, function(elem) { + if (elem !== root) { + assert_equals(elem, result[i++], "The result in index " + i + " should be in tree order.") + } + }) + }, type + ".findAll tree order"); +} + +/* + * Execute queries with the specified valid selectors for both find() and findAll() + * Only run these tests when results are expected. Don't run for syntax error tests. + * + * context.findAll(selector, refNodes) + * context.findAll(selector) // Only if refNodes is not specified + * root.findAll(selector, context) // Only if refNodes is not specified + * root.findAll(selector, refNodes) // Only if context is not specified + * root.findAll(selector) // Only if neither context nor refNodes is specified + * + * Equivalent tests will be run for .find() as well. + */ +function runValidSelectorTest(type, root, selectors, docType) { + var nodeType = getNodeType(root); + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + + var ctx = s["ctx"]; + var ref = s["ref"]; + + if (!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) { + //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) + var foundall, found, context, refNodes, refArray; + + if (s["testType"] & TEST_FIND) { + + + /* + * If ctx and ref are specified: + * context.findAll(selector, refNodes) + * context.find(selector, refNodes) + */ + if (ctx && ref) { + context = root.querySelector(ctx); + refNodes = root.querySelectorAll(ref); + refArray = Array.prototype.slice.call(refNodes, 0); + + test(function() { + foundall = context.findAll(q, refNodes); + verifyNodeList(foundall, expect); + }, type + " [Context Element].findAll: " + n + " (with refNodes NodeList): " + q); + + test(function() { + foundall = context.findAll(q, refArray); + verifyNodeList(foundall, expect); + }, type + " [Context Element].findAll: " + n + " (with refNodes Array): " + q); + + test(function() { + found = context.find(q, refNodes); + verifyElement(found, foundall, expect) + }, type + " [Context Element].find: " + n + " (with refNodes NodeList): " + q); + + test(function() { + found = context.find(q, refArray); + verifyElement(found, foundall, expect) + }, type + " [Context Element].find: " + n + " (with refNodes Array): " + q); + } + + + /* + * If ctx is specified, ref is not: + * context.findAll(selector) + * context.find(selector) + * root.findAll(selector, context) + * root.find(selector, context) + */ + if (ctx && !ref) { + context = root.querySelector(ctx); + + test(function() { + foundall = context.findAll(q); + verifyNodeList(foundall, expect); + }, type + " [Context Element].findAll: " + n + " (with no refNodes): " + q); + + test(function() { + found = context.find(q); + verifyElement(found, foundall, expect) + }, type + " [Context Element].find: " + n + " (with no refNodes): " + q); + + test(function() { + foundall = root.findAll(q, context); + verifyNodeList(foundall, expect); + }, type + " [Root Node].findAll: " + n + " (with refNode Element): " + q); + + test(function() { + foundall = root.find(q, context); + verifyElement(found, foundall, expect); + }, type + " [Root Node].find: " + n + " (with refNode Element): " + q); + } + + /* + * If ref is specified, ctx is not: + * root.findAll(selector, refNodes) + * root.find(selector, refNodes) + */ + if (!ctx && ref) { + refNodes = root.querySelectorAll(ref); + refArray = Array.prototype.slice.call(refNodes, 0); + + test(function() { + foundall = root.findAll(q, refNodes); + verifyNodeList(foundall, expect); + }, type + " [Root Node].findAll: " + n + " (with refNodes NodeList): " + q); + + test(function() { + foundall = root.findAll(q, refArray); + verifyNodeList(foundall, expect); + }, type + " [Root Node].findAll: " + n + " (with refNodes Array): " + q); + + test(function() { + found = root.find(q, refNodes); + verifyElement(found, foundall, expect); + }, type + " [Root Node].find: " + n + " (with refNodes NodeList): " + q); + + test(function() { + found = root.find(q, refArray); + verifyElement(found, foundall, expect); + }, type + " [Root Node].find: " + n + " (with refNodes Array): " + q); + } + + /* + * If neither ctx nor ref is specified: + * root.findAll(selector) + * root.find(selector) + */ + if (!ctx && !ref) { + test(function() { + foundall = root.findAll(q); + verifyNodeList(foundall, expect); + }, type + ".findAll: " + n + " (with no refNodes): " + q); + + test(function() { + found = root.find(q); + verifyElement(found, foundall, expect); + }, type + ".find: " + n + " (with no refNodes): " + q); + } + } + } else { + //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) + } + } +} + +/* + * Execute queries with the specified invalid selectors for both find() and findAll() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ +function runInvalidSelectorTestFind(type, root, selectors) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + test(function() { + assert_throws("SyntaxError", function() { + root.find(q) + }) + }, type + ".find: " + n + ": " + q); + + test(function() { + assert_throws("SyntaxError", function() { + root.findAll(q) + }) + }, type + ".findAll: " + n + ": " + q); + } +} + +function verifyNodeList(resultAll, expect) { + assert_not_equals(resultAll, null, "The method should not return null."); + assert_equals(resultAll.length, e.length, "The method should return the expected number of matches."); + + for (var i = 0; i < e.length; i++) { + assert_not_equals(resultAll[i], null, "The item in index " + i + " should not be null.") + assert_equals(resultAll[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID."); + assert_false(resultAll[i].hasAttribute("data-clone"), "This should not be a cloned element."); + } +} + +function verifyElement(result, resultAll, expect) { + if (expect.length > 0) { + assert_not_equals(result, null, "The method should return a match.") + assert_equals(found.getAttribute("id"), e[0], "The method should return the first match."); + assert_equals(result, resultAll[0], "The result should match the first item from querySelectorAll."); + assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element."); + } else { + assert_equals(result, null, "The method should not match anything."); + } +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/serve.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/serve.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/serve.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/serve.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import argparse import json -import logging import os import signal import socket @@ -19,6 +18,8 @@ sys.path.insert(1, os.path.join(repo_root, "tools", "wptserve")) from wptserve import server as wptserve, handlers from wptserve.router import any_method +from wptserve.logger import set_logger + sys.path.insert(1, os.path.join(repo_root, "tools", "pywebsocket", "src")) from mod_pywebsocket import standalone as pywebsocket @@ -39,12 +40,12 @@ u"天気ă®č‰Żă„ć—Ą", u"Ă©lève"] -logger = None - -def default_logger(level): +def setup_logger(level): + import logging + global logger logger = logging.getLogger("web-platform-tests") logging.basicConfig(level=getattr(logging, level.upper())) - return logger + set_logger(logger) def open_socket(port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -323,12 +324,10 @@ return rv def main(): - global logger - config = load_config("config.default.json", "config.json") - logger = default_logger(config["log_level"]) + setup_logger(config["log_level"]) config_, servers = start(config) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/runner/update_manifest.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/runner/update_manifest.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/runner/update_manifest.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/runner/update_manifest.py 2014-11-26 21:45:59.000000000 +0000 @@ -10,9 +10,9 @@ import manifest def main(request, response): - manifest_path = os.path.join(root, "MANIFEST.json") - manifest.update_manifest(root, **{"rebuild": False, - "local_changes": True, - "path": manifest_path}) + path = os.path.join(root, "MANIFEST.json") + manifest_file = manifest.load(path) + manifest.update(root, "/", manifest_file) + manifest.write(manifest_file, path) return [("Content-Type", "application/json")], json.dumps({"url": "/MANIFEST.json"}) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/scripts/manifest.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/scripts/manifest.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/scripts/manifest.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/scripts/manifest.py 2014-11-26 21:45:59.000000000 +0000 @@ -9,6 +9,8 @@ import sys import urlparse +from StringIO import StringIO +from abc import ABCMeta, abstractmethod, abstractproperty from collections import defaultdict from fnmatch import fnmatch @@ -20,10 +22,8 @@ return git -def setup_git(repo_path): - assert os.path.exists(os.path.join(repo_path, ".git")) - global git - git = get_git_func(repo_path) +def is_git_repo(tests_root): + return os.path.exists(os.path.join(tests_root, ".git")) _repo_root = None @@ -36,79 +36,130 @@ manifest_name = "MANIFEST.json" -exclude_php_hack = True ref_suffixes = ["_ref", "-ref"] wd_pattern = "*.py" blacklist = ["/", "/tools/", "/resources/", "/common/", "/conformance-checkers/"] + logging.basicConfig() logger = logging.getLogger("manifest") logger.setLevel(logging.DEBUG) +def rel_path_to_url(rel_path, url_base="/"): + assert not os.path.isabs(rel_path) + if url_base[0] != "/": + url_base = "/" + url_base + if url_base[-1] != "/": + url_base += "/" + return url_base + rel_path.replace(os.sep, "/") + + +def url_to_rel_path(url, url_base): + url_path = urlparse.urlsplit(url).path + if not url_path.startswith(url_base): + raise ValueError, url + url_path = url_path[len(url_base):] + return url_path + + +def is_blacklisted(url): + for item in blacklist: + if item == "/": + if "/" not in url[1:]: + return True + elif url.startswith(item): + return True + return False + + class ManifestItem(object): + __metaclass__ = ABCMeta + item_type = None - def __init__(self, path): - self.path = path + def __init__(self): + self.manifest = None - def _key(self): - return self.item_type, self.path + @abstractmethod + def key(self): + pass def __eq__(self, other): - if not hasattr(other, "_key"): + if not hasattr(other, "key"): return False - return self._key() == other._key() + return self.key() == other.key() def __hash__(self): - return hash(self._key()) + return hash(self.key()) + @abstractmethod def to_json(self): - return {"path": self.path} + raise NotImplementedError @classmethod - def from_json(self, obj): + def from_json(self, manifest, obj): raise NotImplementedError - @property + @abstractproperty def id(self): - raise NotImplementedError + pass -class TestharnessTest(ManifestItem): - item_type = "testharness" - def __init__(self, path, url, timeout=None): - ManifestItem.__init__(self, path) +class URLManifestItem(ManifestItem): + def __init__(self, url, url_base="/"): + ManifestItem.__init__(self) self.url = url - self.timeout = timeout + self.url_base = url_base @property def id(self): return self.url + def key(self): + return self.item_type, self.url + + @property + def path(self): + return url_to_rel_path(self.url, self.url_base) + def to_json(self): - rv = ManifestItem.to_json(self) - rv.update({"url": self.url}) - if self.timeout: + rv = {"url": self.url} + return rv + + @classmethod + def from_json(cls, manifest, obj): + return cls(obj["url"], + url_base=manifest.url_base) + + +class TestharnessTest(URLManifestItem): + item_type = "testharness" + + def __init__(self, url, url_base="/", timeout=None): + URLManifestItem.__init__(self, url, url_base=url_base) + self.timeout = timeout + + def to_json(self): + rv = {"url": self.url} + if self.timeout is not None: rv["timeout"] = self.timeout return rv @classmethod - def from_json(cls, obj): - return cls(obj["path"], - obj["url"], + def from_json(cls, manifest, obj): + return cls(obj["url"], + url_base=manifest.url_base, timeout=obj.get("timeout")) -class RefTest(ManifestItem): +class RefTest(URLManifestItem): item_type = "reftest" - def __init__(self, path, url, ref_url, ref_type, - timeout=None): + def __init__(self, url, ref_url, ref_type, url_base="/", timeout=None): + URLManifestItem.__init__(self, url, url_base=url_base) if ref_type not in ["==", "!="]: raise ValueError, "Unrecognised ref_type %s" % ref_type - ManifestItem.__init__(self, path) - self.url = url self.ref_url = ref_url self.ref_type = ref_type self.timeout = timeout @@ -117,191 +168,257 @@ def id(self): return (self.url, self.ref_type, self.ref_url) - def _key(self): + def key(self): return self.item_type, self.url, self.ref_type, self.ref_url def to_json(self): - rv = ManifestItem.to_json(self) - rv.update({"url": self.url, - "ref_type": self.ref_type, - "ref_url": self.ref_url}) - if self.timeout: + rv = {"url": self.url, + "ref_type": self.ref_type, + "ref_url": self.ref_url} + if self.timeout is not None: rv["timeout"] = self.timeout return rv @classmethod - def from_json(cls, obj): - return cls(obj["path"], obj["url"], obj["ref_url"], obj["ref_type"], + def from_json(cls, manifest, obj): + return cls(obj["url"], + obj["ref_url"], + obj["ref_type"], + url_base=manifest.url_base, timeout=obj.get("timeout")) -class ManualTest(ManifestItem): +class ManualTest(URLManifestItem): item_type = "manual" - def __init__(self, path, url): - ManifestItem.__init__(self, path) - self.url = url - - @property - def id(self): - return self.url - - def to_json(self): - rv = ManifestItem.to_json(self) - rv.update({"url": self.url}) - return rv - - @classmethod - def from_json(cls, obj): - return cls(obj["path"], obj["url"]) - - -class Stub(ManifestItem): +class Stub(URLManifestItem): item_type = "stub" - def __init__(self, path, url): - ManifestItem.__init__(self, path) - self.url = url - - @property - def id(self): - return self.url - - def to_json(self): - rv = ManifestItem.to_json(self) - rv.update({"url": self.url}) - return rv - - @classmethod - def from_json(cls, obj): - return cls(obj["path"], obj["url"]) - - -class Helper(ManifestItem): +class Helper(URLManifestItem): item_type = "helper" - def __init__(self, path, url): - ManifestItem.__init__(self, path) - self.url = url +class WebdriverSpecTest(ManifestItem): + item_type = "wdspec" + + def __init__(self, path): + ManifestItem.__init__(self) + self.path = path @property def id(self): - return self.url + return self.path def to_json(self): - rv = ManifestItem.to_json(self) - rv.update({"url": self.url}) - return rv - - @classmethod - def from_json(cls, obj): - return cls(obj["path"], obj["url"]) - - -class WebdriverSpecTest(ManifestItem): - item_type = "wdspec" + return {"path": self.path} - @property - def id(self): + def key(self): return self.path @classmethod - def from_json(cls, obj): - return cls(obj["path"]) + def from_json(cls, manifest, obj): + return cls(path=obj["path"]) class ManifestError(Exception): pass +item_types = ["testharness", "reftest", "manual", "helper", "stub", "wdspec"] class Manifest(object): - def __init__(self, git_rev): - self.item_types = [ - "testharness", "reftest", "manual", "helper", "stub", "wdspec"] + def __init__(self, git_rev=None, url_base="/"): + # Dict of item_type: {path: set(manifest_items)} self._data = dict((item_type, defaultdict(set)) - for item_type in self.item_types) + for item_type in item_types) self.rev = git_rev - self.local_changes = LocalChanges() + self.url_base = url_base + self.local_changes = LocalChanges(self) + + def _included_items(self, include_types=None): + if include_types is None: + include_types = item_types + + for item_type in include_types: + paths = self._data[item_type].copy() + for local_types, local_paths in self.local_changes.itertypes(item_type): + for path, items in local_paths.iteritems(): + paths[path] = items + for path in self.local_changes.iterdeleted(): + del paths[path] + + yield item_type, paths def contains_path(self, path): - return any(path in item for item in self._data.itervalues()) + return any(path in paths for _, paths in self._included_items()) def add(self, item): self._data[item.item_type][item.path].add(item) + item.manifest = self def extend(self, items): for item in items: self.add(item) def remove_path(self, path): - for item_type in self.item_types: + for item_type in item_types: if path in self._data[item_type]: del self._data[item_type][path] def itertypes(self, *types): - for item_type in types: - for item in sorted(self._data[item_type].items()): + if not types: + types = None + for item_type, items in self._included_items(types): + for item in sorted(items.items()): yield item def __iter__(self): - for item_type in self.item_types: - for item in self._data[item_type].iteritems(): - yield item + for item in self.itertypes(): + yield item - def __getitem__(self, key): - for items in self._data.itervalues(): - if key in items: - return items[key] + def __getitem__(self, path): + for _, paths in self._data._included_items(): + if path in paths: + return paths[path] raise KeyError + def update(self, + tests_root, + url_base, + new_rev, + committed_changes=None, + local_changes=None): + + if local_changes is None: + local_changes = {} + + if committed_changes is not None: + for rel_path, status in committed_changes: + self.remove_path(rel_path) + if status == "modified": + use_committed = rel_path in local_changes + manifest_items = get_manifest_items(tests_root, + rel_path, + url_base, + use_committed=use_committed) + self.extend(manifest_items) + + self.local_changes = LocalChanges(self) + for rel_path, status in local_changes.iteritems(): + if status == "modified": + items = set(get_manifest_items(tests_root, + rel_path, + url_base, + use_committed=False)) + self.local_changes.extend(items) + else: + self.local_changes.add_deleted(path) + + self.rev = new_rev + self.url_base = url_base + def to_json(self): - items = defaultdict(list) - for test_path, tests in self.itertypes(*self.item_types): - for test in tests: - items[test.item_type].append(test.to_json()) - - rv = {"rev":self.rev, - "local_changes":self.local_changes.to_json(), - "items":items} + out_items = { + item_type: sorted( + test.to_json() + for _, tests in items.iteritems() + for test in tests + ) + for item_type, items in self._data.iteritems() + } + + rv = {"url_base": self.url_base, + "rev": self.rev, + "local_changes": self.local_changes.to_json(), + "items": out_items} return rv @classmethod def from_json(cls, obj): - self = cls(obj["rev"]) + self = cls(git_rev=obj["rev"], + url_base=obj.get("url_base", "/")) if not hasattr(obj, "iteritems"): raise ManifestError - item_classes = {"testharness":TestharnessTest, - "reftest":RefTest, - "manual":ManualTest, - "helper":Helper, + item_classes = {"testharness": TestharnessTest, + "reftest": RefTest, + "manual": ManualTest, + "helper": Helper, "stub": Stub, "wdspec": WebdriverSpecTest} for k, values in obj["items"].iteritems(): - if k not in self.item_types: + if k not in item_types: raise ManifestError for v in values: - manifest_item = item_classes[k].from_json(v) + manifest_item = item_classes[k].from_json(self, v) self.add(manifest_item) - self.local_changes = LocalChanges.from_json(obj["local_changes"]) + self.local_changes = LocalChanges.from_json(self, obj["local_changes"]) return self +class LocalChanges(object): + def __init__(self, manifest): + self.manifest = manifest + self._data = dict((item_type, defaultdict(set)) for item_type in item_types) + self._deleted = set() -class LocalChanges(dict): - def __setitem__(self, path, status): - if status not in ["A", "M", "D"]: - raise ValueError, "Unrecognised status %s for path %s" % (status, path) - dict.__setitem__(self, path, status) + def add(self, item): + self._data[item.item_type][item.path].add(item) + item.manifest = self.manifest + + def extend(self, items): + for item in items: + self.add(item) + + def add_deleted(self, path): + self._deleted.add(path) + + def is_deleted(self, path): + return path in self._deleted + + def itertypes(self, *types): + for item_type in types: + yield item_type, self._data[item_type] + + def iterdeleted(self): + for item in self._deleted: + yield item + + def __getitem__(self, item_type): + return self._data[item_type] def to_json(self): - return [(self[item], item) for item in sorted(self.keys())] + rv = {"items": defaultdict(dict), + "deleted": []} + + rv["deleted"].extend(self._deleted) + + for test_type, paths in self._data.iteritems(): + for path, tests in paths.iteritems(): + rv["items"][test_type][path] = [test.to_json() for test in tests] + + return rv @classmethod - def from_json(cls, obj): - self = cls() - for status, path in obj: - self[path] = status + def from_json(cls, url_base, obj): + self = cls(url_base) + if not hasattr(obj, "iteritems"): + raise ManifestError + + item_classes = {"testharness": TestharnessTest, + "reftest": RefTest, + "manual": ManualTest, + "helper": Helper, + "stub": Stub, + "wdspec": WebdriverSpecTest} + + for test_type, paths in obj["items"].iteritems(): + for path, tests in paths.iteritems(): + for test in tests: + manifest_item = item_classes[test_type].from_json(self.manifest, test) + self.add(manifest_item) + + for item in obj["deleted"]: + self.add_deleted(item) + return self @@ -342,17 +459,33 @@ return match_links, mismatch_links -def get_manifest_items(rel_path): - if rel_path.endswith(os.path.sep): +def get_file(base_path, rel_path, use_committed): + if use_committed: + blob = git("show", "HEAD:%s" % rel_path) + file_obj = ContextManagerStringIO(blob) + else: + path = os.path.join(base_path, rel_path) + file_obj = open(path) + return file_obj + +class ContextManagerStringIO(StringIO): + def __enter__(self): + return self + + def __exit__(self, *args, **kwargs): + self.close() + +def get_manifest_items(tests_root, rel_path, url_base, use_committed=False): + if os.path.isdir(rel_path): return [] - url = "/" + rel_path.replace(os.sep, "/") + url = rel_path_to_url(rel_path, url_base) + path = os.path.join(tests_root, rel_path) - path = os.path.join(get_repo_root(), rel_path) - if not os.path.exists(path): + if not use_committed and not os.path.exists(path): return [] - base_path, filename = os.path.split(path) + dir_path, filename = os.path.split(path) name, ext = os.path.splitext(filename) rel_dir_tree = rel_path.split(os.path.sep) @@ -361,29 +494,25 @@ if filename.startswith("MANIFEST") or filename.startswith("."): return [] - for item in blacklist: - if item == "/": - if "/" not in url[1:]: - return [] - elif url.startswith(item): - return [] + if is_blacklisted(url): + return [] if name.startswith("stub-"): - return [Stub(rel_path, url)] + return [Stub(url)] if name.lower().endswith("-manual"): - return [ManualTest(rel_path, url)] + return [ManualTest(url)] ref_list = [] for suffix in ref_suffixes: if name.endswith(suffix): - return [Helper(rel_path, rel_path)] - elif os.path.exists(os.path.join(base_path, name + suffix + ext)): + return [Helper(url)] + elif os.path.exists(os.path.join(dir_path, name + suffix + ext)): ref_url, ref_ext = url.rsplit(".", 1) ref_url = ref_url + suffix + ext #Need to check if this is the right reftype - ref_list = [RefTest(rel_path, url, ref_url, "==")] + ref_list = [RefTest(url, ref_url, "==")] # wdspec tests are in subdirectories of /webdriver excluding __init__.py # files. @@ -396,21 +525,15 @@ if file_markup_type: timeout = None - if exclude_php_hack: - php_re =re.compile("\.php") - with open(path) as f: - text = f.read() - if php_re.findall(text): - return [] - parser = {"html":lambda x:html5lib.parse(x, treebuilder="etree"), "xhtml":ElementTree.parse, "svg":ElementTree.parse}[file_markup_type] - try: - with open(path) as f: + + with get_file(tests_root, rel_path, use_committed) as f: + try: tree = parser(f) - except: - return [Helper(rel_path, url)] + except: + return [Helper(url)] if hasattr(tree, "getroot"): root = tree.getroot() @@ -427,98 +550,182 @@ pass if get_testharness_scripts(root): - return [TestharnessTest(rel_path, url, timeout=timeout)] + return [TestharnessTest(url, timeout=timeout)] else: match_links, mismatch_links = get_reference_links(root) for item in match_links + mismatch_links: ref_url = urlparse.urljoin(url, item.attrib["href"]) ref_type = "==" if item.attrib["rel"] == "match" else "!=" - reftest = RefTest(rel_path, url, ref_url, ref_type, timeout=timeout) + reftest = RefTest(url, ref_url, ref_type, timeout=timeout) if reftest not in ref_list: ref_list.append(reftest) return ref_list - return [Helper(rel_path, url)] + return [Helper(url)] def abs_path(path): return os.path.abspath(path) -def get_repo_paths(): - data = git("ls-tree", "--name-only", "--full-tree", "-r", "HEAD") - return [item for item in data.split("\n") if not item.endswith(os.path.sep)] +def chunks(data, n): + for i in range(0, len(data) - 1, n): + yield data[i:i+n] -def get_committed_changes(base_rev): - if base_rev is None: - logger.debug("Adding all changesets to the manifest") - return [("A", item) for item in get_repo_paths()] - else: - logger.debug("Updating the manifest from %s to %s" % (base_rev, get_current_rev())) - data = git("diff", "--name-status", base_rev) - return [line.split("\t", 1) for line in data.split("\n") if line] - - -def has_local_changes(): - return git("status", "--porcelain", "--ignore-submodules=untracked").strip() != "" - - -def get_local_changes(): - #This doesn't account for whole directories that have been added - data = git("status", "--porcelain", "--ignore-submodules=all") - rv = LocalChanges() - for line in data.split("\n"): - line = line.strip() - if not line: - continue - status, path = line.split(" ", 1) - if path.endswith(os.path.sep): - logger.warning("Ignoring added directory %s" % path) - continue - if status == "??": - status = "A" - elif status == "R": - old_path, path = tuple(item.strip() for item in path.split("->")) - rv[old_path] = "D" - status = "A" - elif status == "MM": - status = "M" - rv[path] = status - return rv - - -def sync_urls(manifest, updated_files): - for status, path in updated_files: - if status in ("D", "M"): - manifest.remove_path(path) - if status in ("A", "M"): - manifest.extend(get_manifest_items(path)) - - -def sync_local_changes(manifest, local_changes): - if local_changes: - logger.info("Working directory not clean, adding local changes") - prev_local_changes = manifest.local_changes - all_paths = get_repo_paths() - - for path, status in prev_local_changes.iteritems(): - print status, path, path in local_changes - if path not in local_changes: - # If a path was previously marked as deleted but is now back - # we need to readd it to the manifest - if status == "D" and path in all_paths: - local_changes[path] = "A" - # If a path was previously marked as added but is now - # not then we need to remove it from the manifest - elif status == "A" and path not in all_paths: - local_changes[path] = "D" +class TestTree(object): + def __init__(self, tests_root, url_base): + self.tests_root = tests_root + self.url_base = url_base + + def current_rev(self): + pass + + def local_changes(self): + pass + + def comitted_changes(self, base_rev=None): + pass - sync_urls(manifest, ((status, path) for path, status in local_changes.iteritems())) +class GitTree(TestTree): + def __init__(self, tests_root, url_base): + TestTree.__init__(self, tests_root, url_base) + self.git = self.setup_git() -def get_current_rev(): - return git("rev-parse", "HEAD").strip() + def setup_git(self): + assert is_git_repo(self.tests_root) + return get_git_func(self.tests_root) + + def current_rev(self): + return self.git("rev-parse", "HEAD").strip() + + def local_changes(self, path=None): + # -z is stable like --porcelain; see the git status documentation for details + cmd = ["status", "-z", "--ignore-submodules=all"] + if path is not None: + cmd.extend(["--", path]) + + rv = {} + + data = self.git(*cmd) + if data == "": + return rv + + assert data[-1] == "\0" + f = StringIO(data) + + while f.tell() < len(data): + # First two bytes are the status in the stage (index) and working tree, respectively + staged = f.read(1) + worktree = f.read(1) + assert f.read(1) == " " + + if staged == "R": + # When a file is renamed, there are two files, the source and the destination + files = 2 + else: + files = 1 + + filenames = [] + + for i in range(files): + filenames.append("") + char = f.read(1) + while char != "\0": + filenames[-1] += char + char = f.read(1) + + if not is_blacklisted(rel_path_to_url(filenames[0], self.url_base)): + rv.update(self.local_status(staged, worktree, filenames)) + + return rv + + def committed_changes(self, base_rev=None): + if base_rev is None: + logger.debug("Adding all changesets to the manifest") + return [(item, "modified") for item in self.paths()] + + logger.debug("Updating the manifest from %s to %s" % (base_rev, self.current_rev())) + rv = [] + data = self.git("diff", "-z", "--name-status", base_rev + "..HEAD") + items = data.split("\0") + for status, filename in chunks(items, 2): + if is_blacklisted(rel_path_to_url(filename, self.url_base)): + continue + if status == "D": + rv.append((filename, "deleted")) + else: + rv.append((filename, "modified")) + return rv + + def paths(self): + data = self.git("ls-tree", "--name-only", "--full-tree", "-r", "HEAD") + return [item for item in data.split("\n") if not item.endswith(os.path.sep)] + + def local_status(self, staged, worktree, filenames): + # Convert the complex range of statuses that git can have to two values + # we care about; "modified" and "deleted" and return a dictionary mapping + # filenames to statuses + + rv = {} + + if (staged, worktree) in [("D", "D"), ("A", "U"), ("U", "D"), ("U", "A"), + ("D", "U"), ("A", "A"), ("U", "U")]: + raise Exception("Can't operate on tree containing unmerged paths") + + if staged == "R": + assert len(filenames) == 2 + dest, src = filenames + rv[dest] = "modified" + rv[src] = "deleted" + else: + assert len(filenames) == 1 + + filename = filenames[0] + + if staged == "D" or worktree == "D": + # Actually if something is deleted in the index but present in the worktree + # it will get included by having a status of both "D " and "??". + # It isn't clear whether that's a bug + rv[filename] = "deleted" + elif staged == "?" and worktree == "?": + # A new file. If it's a directory, recurse into it + if os.path.isdir(os.path.join(self.tests_root, filename)): + rv.update(self.local_changes(filename)) + else: + rv[filename] = "modified" + else: + rv[filename] = "modified" + + return rv + +class NoVCSTree(TestTree): + """Subclass that doesn't depend on git but assumes that all changes are comitted""" + + ignore = ["*.py[c|0]", "*~", "#*"] + + def current_rev(self): + return None + + def local_changes(self): + return None + + def committed_changes(self, base_rev=None): + if base_rev is not None: + raise ValueError("Tried to update a tree with no VCS against a base_rev") + + rv = [] + for dir_path, dir_names, filenames in os.walk(self.tests_root): + for filename in filenames: + if any(fnmatch(filename, pattern) for pattern in self.ignore): + continue + rel_path = os.path.relpath(os.path.join(dir_path, filename), + self.tests_root) + if is_blacklisted(rel_path_to_url(rel_path, self.url_base)): + continue + rv.append((rel_path, "modified")) + return rv def load(manifest_path): @@ -535,7 +742,7 @@ return manifest -def update(manifest): +def update(tests_root, url_base, manifest, ignore_local=False): global ElementTree global html5lib @@ -546,10 +753,21 @@ import html5lib - sync_urls(manifest, get_committed_changes(manifest.rev)) - sync_local_changes(manifest, get_local_changes()) + if is_git_repo(tests_root): + tests_tree = GitTree(tests_root, url_base) + else: + tests_tree = NoVCSTree(tests_root, url_base) - manifest.rev = get_current_rev() + if not ignore_local: + local_changes = tests_tree.local_changes() + else: + local_changes = None + + manifest.update(tests_root, + url_base, + tests_tree.current_rev(), + tests_tree.committed_changes(manifest.rev), + local_changes) def write(manifest, manifest_path): @@ -557,43 +775,51 @@ json.dump(manifest.to_json(), f, sort_keys=True, indent=2, separators=(',', ': ')) -def update_manifest(repo_path, **kwargs): - setup_git(repo_path) +def update_from_cli(**kwargs): + tests_root = kwargs["tests_root"] + path = kwargs["path"] + assert tests_root is not None if not kwargs.get("rebuild", False): - manifest = load(kwargs["path"]) + manifest = load(path) else: manifest = Manifest(None) - if has_local_changes() and not kwargs.get("local_changes", False): - logger.info("Not writing manifest because working directory is not clean.") - else: - logger.info("Updating manifest") - update(manifest) - write(manifest, kwargs["path"]) + + logger.info("Updating manifest") + update(tests_root, + kwargs["url_base"], + manifest, + ignore_local=kwargs.get("ignore_local", False)) + write(manifest, path) + + +def abs_path(path): + return os.path.abspath(os.path.expanduser(path)) def create_parser(): parser = argparse.ArgumentParser() parser.add_argument( - "-p", "--path", default=os.path.join(get_repo_root(), "MANIFEST.json"), - help="path to manifest file") + "-p", "--path", type=abs_path, help="Path to manifest file.") + parser.add_argument( + "--tests-root", type=abs_path, help="Path to root of tests.") parser.add_argument( "-r", "--rebuild", action="store_true", default=False, - help="force a full rebuild of the manifest rather than updating " - "incrementally") + help="Force a full rebuild of the manifest.") parser.add_argument( - "-c", "--experimental-include-local-changes", action="store_true", default=False, - help="include local changes in the manifest rather than just committed " - "changes (experimental)") + "--ignore-local", action="store_true", default=False, + help="Don't include uncommitted local changes in the manifest.") + parser.add_argument( + "--url-base", action="store", default="/", + help="Base url to use as the mount point for tests in this manifest.") return parser if __name__ == "__main__": - try: - get_repo_root() - except subprocess.CalledProcessError: - print "Script must be inside a web-platform-tests git clone." - sys.exit(1) opts = create_parser().parse_args() - update_manifest(get_repo_root(), - path=opts.path, - rebuild=opts.rebuild, - local_changes=opts.experimental_include_local_changes) + + if opts.tests_root is None: + opts.tests_root = get_repo_root() + + if opts.path is None: + opts.path = os.path.join(opts.tests_root, "MANIFEST.json") + + update_from_cli(**vars(opts)) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/searchcontext.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/searchcontext.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/searchcontext.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/searchcontext.py 2014-11-26 21:45:59.000000000 +0000 @@ -11,14 +11,6 @@ """Find all elements matching a css selector.""" return self._find_elements('css selector', selector) - def find_element_by_id(self, id): - """Find the first element with the given id.""" - return self._find_element('id', id) - - def find_elements_by_id(self, id): - """Find all elements with the given id.""" - return self._find_elements('id', id) - def find_element_by_link_text(self, text): """Find the first link with the given text.""" return self._find_element('link text', text) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/webelement.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/webelement.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/webelement.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/webdriver/webdriver/webelement.py 2014-11-26 21:45:59.000000000 +0000 @@ -28,10 +28,16 @@ """Get the value of an element property or attribute.""" return self.execute('GET', '/attribute/%s' % name, 'getElementAttribute') - def get_text(self): + @property + def text(self): """Get the visible text for this element.""" return self.execute('GET', '/text', 'text') + @property + def tag_name(self): + """Get the tag name for this element""" + return self.execute('GET', '/name', 'getElementTagName') + def click(self): """Click on this element.""" return self.execute('POST', '/click', 'click') diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,6 +1,5 @@ import cgi import json -import logging import os import traceback import urllib @@ -9,14 +8,13 @@ from constants import content_types from pipes import Pipeline, template from ranges import RangeParser +from request import Authentication from response import MultipartContent from utils import HTTPException -logger = logging.getLogger("wptserve") - __all__ = ["file_handler", "python_script_handler", "FunctionHandler", "handler", "json_handler", - "as_is_handler", "ErrorHandler"] + "as_is_handler", "ErrorHandler", "BasicAuthHandler"] def guess_content_type(path): @@ -27,9 +25,34 @@ return "application/octet-stream" + +def filesystem_path(base_path, request, url_base="/"): + if base_path is None: + base_path = request.doc_root + + path = request.url_parts.path + + if path.startswith(url_base): + path = path[len(url_base):] + + if ".." in path: + raise HTTPException(404) + + new_path = os.path.join(base_path, path) + + # Otherwise setting path to / allows access outside the root directory + if not new_path.startswith(base_path): + raise HTTPException(404) + + return new_path + class DirectoryHandler(object): + def __init__(self, base_path=None, url_base="/"): + self.base_path = base_path + self.url_base = url_base + def __call__(self, request, response): - path = request.filesystem_path + path = filesystem_path(self.base_path, request, self.url_base) assert os.path.isdir(path) @@ -45,8 +68,13 @@ "items": "\n".join(self.list_items(request, path))} def list_items(self, request, path): + # TODO: this won't actually list all routes, only the + # ones that correspond to a real filesystem path. It's + # not possible to list every route that will match + # something, but it should be possible to at least list the + # statically defined ones base_path = request.url_parts.path - filesystem_base = request.filesystem_path + if not base_path.endswith("/"): base_path += "/" if base_path != "/": @@ -55,7 +83,7 @@ {"link": link, "name": ".."}) for item in sorted(os.listdir(path)): link = cgi.escape(urllib.quote(item)) - if os.path.isdir(os.path.join(filesystem_base, item)): + if os.path.isdir(os.path.join(path, item)): link += "/" class_ = "dir" else: @@ -68,11 +96,16 @@ class FileHandler(object): + def __init__(self, base_path=None, url_base="/"): + self.base_path = base_path + self.url_base = url_base + self.directory_handler = DirectoryHandler(self.base_path) + def __call__(self, request, response): - path = request.filesystem_path + path = filesystem_path(self.base_path, request, self.url_base) if os.path.isdir(path): - return directory_handler(request, response) + return self.directory_handler(request, response) try: #This is probably racy with some other process trying to change the file file_size = os.stat(path).st_size @@ -123,7 +156,8 @@ except IOError: return [] else: - data = template(request, data) + if use_sub: + data = template(request, data) return [tuple(item.strip() for item in line.split(":", 1)) for line in data.splitlines() if line] @@ -167,26 +201,32 @@ file_handler = FileHandler() -def python_script_handler(request, response): - path = request.filesystem_path +class PythonScriptHandler(object): + def __init__(self, base_path=None, url_base="/"): + self.base_path = base_path + self.url_base = url_base - try: - environ = {"__file__": path} - execfile(path, environ, environ) - if "main" in environ: - handler = FunctionHandler(environ["main"]) - handler(request, response) - else: - raise HTTPException(500) - except IOError: - raise HTTPException(404) + def __call__(self, request, response): + path = filesystem_path(self.base_path, request, self.url_base) + try: + environ = {"__file__": path} + execfile(path, environ, environ) + if "main" in environ: + handler = FunctionHandler(environ["main"]) + handler(request, response) + else: + raise HTTPException(500, "No main function in script %s" % path) + except IOError: + raise HTTPException(404) + +python_script_handler = PythonScriptHandler() def FunctionHandler(func): def inner(request, response): try: rv = func(request, response) - except: + except Exception: msg = traceback.format_exc() raise HTTPException(500, message=msg) if rv is not None: @@ -226,15 +266,50 @@ return FunctionHandler(inner) -def as_is_handler(request, response): - path = request.filesystem_path - try: - with open(path) as f: - response.writer.write_content(f.read()) - response.close_connection = True - except IOError: - raise HTTPException(404) +class AsIsHandler(object): + def __init__(self, base_path=None, url_base="/"): + self.base_path = base_path + self.url_base = url_base + + def __call__(self, request, response): + path = filesystem_path(self.base_path, request, self.url_base) + + try: + with open(path) as f: + response.writer.write_content(f.read()) + response.close_connection = True + except IOError: + raise HTTPException(404) + +as_is_handler = AsIsHandler() + +class BasicAuthHandler(object): + def __init__(self, handler, user, password): + """ + A Basic Auth handler + + :Args: + - handler: a secondary handler for the request after authentication is successful (example file_handler) + - user: string of the valid user name or None if any / all credentials are allowed + - password: string of the password required + """ + self.user = user + self.password = password + self.handler = handler + + def __call__(self, request, response): + if "authorization" not in request.headers: + response.status = 401 + response.headers.set("WWW-Authenticate", "Basic") + return response + else: + auth = Authentication(request.headers) + if self.user is not None and (self.user != auth.username or self.password != auth.password): + response.set_error(403, "Invalid username or password") + return response + return self.handler(request, response) +basic_auth_handler = BasicAuthHandler(file_handler, None, None) class ErrorHandler(object): def __init__(self, status): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/logger.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/logger.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/logger.py 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/logger.py 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,29 @@ +class NoOpLogger(object): + def critical(self, msg): + pass + + def error(self, msg): + pass + + def info(self, msg): + pass + + def warning(self, msg): + pass + + def debug(self, msg): + pass + +logger = NoOpLogger() +_set_logger = False + +def set_logger(new_logger): + global _set_logger + if _set_logger: + raise Exception("Logger must be set at most once") + global logger + logger = new_logger + _set_logger = True + +def get_logger(): + return logger diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/pipes.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/pipes.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/pipes.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/pipes.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,14 +1,11 @@ from cgi import escape import gzip as gzip_module -import logging import re import time import types import uuid from cStringIO import StringIO -logger = logging.getLogger("wptserve") - def resolve_content(response): rv = "".join(item for item in response.iter_content()) @@ -289,7 +286,7 @@ token = token[1:-1] try: token = int(token) - except: + except ValueError: token = unicode(token, "utf8") return ("index", token) @@ -311,9 +308,9 @@ def __getitem__(self, key): try: - return self.params.first(key) + return self.params.first(key) except KeyError: - return "" + return "" @pipe() @@ -442,7 +439,7 @@ out = StringIO() with gzip_module.GzipFile(fileobj=out, mode="w") as f: - f.write(content) + f.write(content) response.content = out.getvalue() response.headers.set("Content-Length", len(response.content)) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/request.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/request.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/request.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/request.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,8 +1,6 @@ import base64 import cgi import Cookie -import logging -import os import StringIO import tempfile import urlparse @@ -10,7 +8,6 @@ import stash from utils import HTTPException -logger = logging.getLogger("wptserve") missing = object() @@ -173,10 +170,6 @@ Request path as it appears in the HTTP request. - .. attribute:: filesystem_path - - Request path resolved relative to the document root. - .. attribute:: url Absolute URL for the request. @@ -275,7 +268,6 @@ self._POST = None self._cookies = None self._auth = None - self._filesystem_path = None self.server = Server(self) @@ -338,20 +330,6 @@ self._auth = Authentication(self.headers) return self._auth - @property - def filesystem_path(self): - if self._filesystem_path is None: - path = self.url_parts.path - if path.startswith("/"): - path = path[1:] - - if ".." in path: - raise HTTPException(500) - - self._filesystem_path = os.path.join(self.doc_root, path) - logger.debug(self._filesystem_path) - return self._filesystem_path - class RequestHeaders(dict): """Dictionary-like API for accessing request headers.""" @@ -393,7 +371,7 @@ a list""" try: return dict.__getitem__(self, key.lower()) - except: + except KeyError: if default is not missing: return default else: diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/response.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/response.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/response.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/response.py 2014-11-26 21:45:59.000000000 +0000 @@ -2,17 +2,15 @@ from datetime import datetime, timedelta import Cookie import json -import logging import types import uuid import socket from constants import response_codes +from logger import get_logger -logger = logging.getLogger("wptserve") missing = object() - class Response(object): """Object representing the response to a HTTP request @@ -77,6 +75,8 @@ self.headers = ResponseHeaders() self.content = [] + self.logger = get_logger() + @property def status(self): return self._status @@ -213,7 +213,7 @@ ("Content-Length", len(data))] self.content = data if code == 500: - logger.error(message) + self.logger.error(message) class MultipartContent(object): @@ -403,7 +403,7 @@ self.write_default_headers() self.write("\r\n") - if not "content-length" in self._headers_seen: + if "content-length" not in self._headers_seen: self._response.close_connection = True if not self._response.explicit_flush: self.flush() diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/router.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/router.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/router.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/router.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,10 +1,8 @@ import itertools -import logging import re import types -logger = logging.getLogger("wptserve") -logger.setLevel(logging.DEBUG) +from logger import get_logger any_method = object() @@ -51,6 +49,8 @@ for token in tokens: re_parts.append(func_map[token[0]](token)) + if self.star_seen: + re_parts.append(")") re_parts.append("$") return re.compile("".join(re_parts)) @@ -70,7 +70,7 @@ if self.star_seen: raise ValueError("Star seen after star in regexp") self.star_seen = True - return "(.*)" + return "(.*" def compile_path_match(route_pattern): """tokens: / or literal or match or *""" @@ -97,6 +97,7 @@ def __init__(self, doc_root, routes): self.doc_root = doc_root self.routes = [] + self.logger = get_logger() for route in reversed(routes): self.register(*route) @@ -111,7 +112,8 @@ a request path matches this route. Match patterns consist of either literal text, match groups, denoted {name}, which match any character except /, - and, at most one \*, which matches any character. + and, at most one \*, which matches and character and + creates a match group to the end of the string. If there is no leading "/" on the pattern, this is automatically implied. For example:: @@ -120,23 +122,24 @@ Would match `/api/test/data.json` or `/api/test/test2/data.json`, but not `/api/test/data.py`. - The match groups, and anything matching the * are made - available in the request object as a dictionary through - the route_match property. For example, given the route - pattern above and the path `/api/test/data.json`, the - route_match property would contain:: + The match groups are made available in the request object + as a dictionary through the route_match property. For + example, given the route pattern above and the path + `/api/test/data.json`, the route_match property would + contain:: - {"resource": "test", "*": "data"} + {"resource": "test", "*": "data.json"} :param handler: Function that will be called to process matching requests. This must take two parameters, the request object and the response object. + """ if type(methods) in types.StringTypes or methods is any_method: methods = [methods] for method in methods: self.routes.append((method, compile_path_match(path), handler)) - logger.debug("Route pattern: %s" % self.routes[-1][1].pattern) + self.logger.debug("Route pattern: %s" % self.routes[-1][1].pattern) def get_handler(self, request): """Get a handler for a request or None if there is no handler. @@ -154,7 +157,7 @@ name = handler.__name__ else: name = handler.__class__.__name__ - logger.debug("Found handler %s" % name) + self.logger.debug("Found handler %s" % name) match_parts = m.groupdict().copy() if len(match_parts) < len(m.groups()): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/server.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/server.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/server.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/tools/wptserve/wptserve/server.py 2014-11-26 21:45:59.000000000 +0000 @@ -1,6 +1,5 @@ import BaseHTTPServer import errno -import logging import os import re import socket @@ -12,16 +11,14 @@ import types import urlparse +import routes as default_routes +from logger import get_logger from request import Server, Request from response import Response from router import Router -import routes as default_routes from utils import HTTPException -logger = logging.getLogger("wptserve") -logger.setLevel(logging.DEBUG) - """HTTP server designed for testing purposes. The server is designed to provide flexibility in the way that @@ -67,6 +64,7 @@ self.rules = {} for rule in reversed(rules): self.register(*rule) + self.logger = get_logger() def register(self, methods, input_path, output_path): """Register a rewrite rule. @@ -95,7 +93,7 @@ if split_url.path in self.rules: methods, destination = self.rules[split_url.path] if "*" in methods or request_handler.command in methods: - logger.debug("Rewriting request path %s to %s" % + self.logger.debug("Rewriting request path %s to %s" % (request_handler.path, destination)) new_url = list(split_url) new_url[2] = destination @@ -106,12 +104,13 @@ class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): allow_reuse_address = True acceptable_errors = (errno.EPIPE, errno.ECONNABORTED) + request_queue_size = 2000 # Ensure that we don't hang on shutdown waiting for requests daemon_threads = True - def __init__(self, server_address, RequestHandlerClass, router, rewriter, bind_hostname, config=None, - use_ssl=False, certificate=None, **kwargs): + def __init__(self, server_address, RequestHandlerClass, router, rewriter, bind_hostname, + config=None, use_ssl=False, key_file=None, certificate=None, **kwargs): """Server for HTTP(s) Requests :param server_address: tuple of (server_name, port) @@ -130,7 +129,9 @@ :param use_ssl: Boolean indicating whether the server should use SSL - :param certificate: Certificate to use if SSL is enabled. + :param key_file: Path to key file to use if SSL is enabled. + + :param certificate: Path to certificate to use if SSL is enabled. :param bind_hostname True to bind the server to both the hostname and port specified in the server_address parameter. @@ -141,6 +142,7 @@ self.rewriter = rewriter self.scheme = "https" if use_ssl else "http" + self.logger = get_logger() if bind_hostname: hostname_port = server_address @@ -153,13 +155,14 @@ if config is not None: Server.config = config else: - logger.debug("Using default configuration") + self.logger.debug("Using default configuration") Server.config = {"host": server_address[0], "domains": {"": server_address[0]}, "ports": {"http": [self.server_address[1]]}} if use_ssl: self.socket = ssl.wrap_socket(self.socket, + keyfile=key_file, certfile=certificate, server_side=True) @@ -174,7 +177,7 @@ error.errno in self.acceptable_errors)): pass # remote hang up before the result is sent else: - logger.error(traceback.format_exc()) + self.logger.error(traceback.format_exc()) class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): @@ -184,6 +187,7 @@ def handle_one_request(self): response = None + logger = get_logger() try: self.close_connection = False request_line_is_valid = self.get_request_line() @@ -217,12 +221,16 @@ response.set_error(e.code, e.message) except Exception as e: if e.message: - err = e.message + err = [e.message] else: - err = traceback.format_exc() - response.set_error(500, err) - logger.info("%i %s %s (%s) %i" % (response.status[0], request.method, - request.request_path, request.headers.get('Referer'), request.raw_input.length)) + err = [] + err.append(traceback.format_exc()) + response.set_error(500, "\n".join(err)) + logger.debug("%i %s %s (%s) %i" % (response.status[0], + request.method, + request.request_path, + request.headers.get('Referer'), + request.raw_input.length)) if not response.writer.content_written: response.write() @@ -257,10 +265,10 @@ self.close_connection = True return False if len(self.raw_requestline) > 65536: - self.requestline = '' - self.request_version = '' - self.command = '' - return False + self.requestline = '' + self.request_version = '' + self.command = '' + return False if not self.raw_requestline: self.close_connection = True return True @@ -273,7 +281,8 @@ :param server_cls: Class to use for the server (default depends on ssl vs non-ssl) :param handler_cls: Class to use for the RequestHandler :param use_ssl: Use a SSL server if no explicit server_cls is supplied - :param certificate: Certificate file to use if ssl is enabled + :param key_file: Path to key file to use if ssl is enabled + :param certificate: Path to certificate file to use if ssl is enabled :param router_cls: Router class to use when matching URLs to handlers :param doc_root: Document root for serving files :param routes: List of routes with which to initialize the router @@ -315,7 +324,7 @@ """ def __init__(self, host="127.0.0.1", port=8000, server_cls=None, handler_cls=WebTestRequestHandler, - use_ssl=False, certificate=None, router_cls=Router, + use_ssl=False, key_file=None, certificate=None, router_cls=Router, doc_root=os.curdir, routes=None, rewriter_cls=RequestRewriter, bind_hostname=True, rewrites=None, config=None): @@ -329,11 +338,14 @@ self.rewriter = rewriter_cls(rewrites if rewrites is not None else []) self.use_ssl = use_ssl + self.logger = get_logger() if server_cls is None: server_cls = WebTestServer if use_ssl: + if key_file is not None: + assert os.path.exists(key_file) assert certificate is not None and os.path.exists(certificate) try: @@ -344,12 +356,13 @@ config=config, bind_hostname=bind_hostname, use_ssl=use_ssl, + key_file=key_file, certificate=certificate) self.started = False _host, self.port = self.httpd.socket.getsockname() except Exception: - logger.error('Init failed! You may need to modify your hosts file. Refer to README.md.'); + self.logger.error('Init failed! You may need to modify your hosts file. Refer to README.md.'); raise def start(self, block=False): @@ -357,7 +370,7 @@ :param block: True to run the server on the current thread, blocking, False to run on a separate thread.""" - logger.info("Starting http server on %s:%s" % (self.host, self.port)) + self.logger.info("Starting http server on %s:%s" % (self.host, self.port)) self.started = True if block: self.httpd.serve_forever() @@ -378,7 +391,7 @@ self.httpd.server_close() self.server_thread.join() self.server_thread = None - logger.info("Stopped http server on %s:%s" % (self.host, self.port)) + self.logger.info("Stopped http server on %s:%s" % (self.host, self.port)) except AttributeError: pass self.started = False diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/url/urltestdata.txt thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/url/urltestdata.txt --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/url/urltestdata.txt 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/url/urltestdata.txt 2014-11-26 21:45:59.000000000 +0000 @@ -27,10 +27,10 @@ :/ s:http h:example.org p:/foo/:/ :\\ s:http h:example.org p:/foo/:/ :# s:http h:example.org p:/foo/: f:# -# s:http h:example.org p:/foo/bar f:# -#/ s:http h:example.org p:/foo/bar f:#/ -#\\ s:http h:example.org p:/foo/bar f:#\\ -#;? s:http h:example.org p:/foo/bar f:#;? +\# s:http h:example.org p:/foo/bar f:# +\#/ s:http h:example.org p:/foo/bar f:#/ +\#\\ s:http h:example.org p:/foo/bar f:#\\ +\#;? s:http h:example.org p:/foo/bar f:#;? ? s:http h:example.org p:/foo/bar q:? / s:http h:example.org p:/ :23 s:http h:example.org p:/foo/:23 @@ -91,13 +91,21 @@ /a/\s/c s:http h:example.org p:/a/%20/c /a%2fc s:http h:example.org p:/a%2fc /a/%2f/c s:http h:example.org p:/a/%2f/c -#\u03B2 s:http h:example.org p:/foo/bar f:#\u03B2 +\#\u03B2 s:http h:example.org p:/foo/bar f:#%CE%B2 data:text/html,test#test s:data p:text/html,test f:#test # Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/file.html + +# Basic canonicalization, uppercase should be converted to lowercase file:c:\\foo\\bar.html file:///tmp/mock/path s:file p:/c:/foo/bar.html + +# Spaces should fail \s\sFile:c|////foo\\bar.html s:file p:/c:////foo/bar.html + +# This should fail C|/foo/bar s:file p:/C:/foo/bar + +# This should fail /C|\\foo\\bar s:file p:/C:/foo/bar //C|/foo/bar s:file p:/C:/foo/bar //server/file s:file h:server p:/file @@ -158,7 +166,7 @@ http://www.google.com/foo?bar=baz#\s\u00BB s:http h:www.google.com p:/foo q:?bar=baz f:#\s%C2%BB http://[www.google.com]/ http://www.google.com s:http h:www.google.com p:/ -http://192.0x00A80001 s:http h:192.0x00a80001 p:/ +http://192.0x00A80001 s:http h:192.168.0.1 p:/ http://www/foo%2Ehtml s:http h:www p:/foo%2Ehtml http://www/foo/%2E/html s:http h:www p:/foo/html http://user:pass@/ @@ -251,23 +259,38 @@ //www.example2.com s:http h:www.example2.com p:/ # Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/host.html + +# Basic canonicalization, uppercase should be converted to lowercase http://ExAmPlE.CoM http://other.com/ s:http p:/ h:example.com + +# Spaces should fail http://example\sexample.com + +# This should fail http://Goo%20\sgoo%7C|.com # U+3000 is mapped to U+0020 (space) which is disallowed http://GOO\u00a0\u3000goo.com +# Other types of space (no-break, zero-width, zero-width-no-break) are +# name-prepped away to nothing. # U+200B, U+2060, and U+FEFF, are ignored http://GOO\u200b\u2060\ufeffgoo.com s:http p:/ h:googoo.com +# Ideographic full stop (full-width period for Chinese, etc.) should be +# treated as a dot. # U+3002 is mapped to U+002E (dot) http://www.foo\u3002bar.com s:http p:/ h:www.foo.bar.com +# Invalid unicode characters should fail... # U+FDD0 is disallowed; %ef%b7%90 is U+FDD0 http://\ufdd0zyx.com + +# ...This is the same as previous but escaped. http://%ef%b7%90zyx.com +# Test name prepping, fullwidth input should be converted to ASCII and NOT +# IDN-ized. This is "Go" in fullwidth UTF-8/UTF-16. http://\uff27\uff4f.com s:http p:/ h:go.com # URL spec forbids the following. @@ -279,7 +302,7 @@ http://\uff05\uff10\uff10.com http://%ef%bc%85%ef%bc%90%ef%bc%90.com -# Basic IDN support +# Basic IDN support, UTF-8 and UTF-16 input should be converted to IDN http://\u4f60\u597d\u4f60\u597d s:http p:/ h:xn--6qqa088eba # Invalid escaped characters should fail and the percents should be @@ -290,10 +313,11 @@ http://%25 http://hello%00 +# Escaped numbers should be treated like IP addresses if they are. # No special handling for IPv4 or IPv4-like URLs -http://%30%78%63%30%2e%30%32%35%30.01 s:http p:/ h:127.0.0.1 +http://%30%78%63%30%2e%30%32%35%30.01 s:http p:/ h:192.168.0.1 http://%30%78%63%30%2e%30%32%35%30.01%2e s:http p:/ h:0xc0.0250.01. -http://192.168.0.257 s:http p:/ h:192.168.0.257 +http://192.168.0.257 # Invalid escaping should trigger the regular host error handling. http://%3g%78%63%30%2e%30%32%35%30%2E.01 @@ -302,8 +326,15 @@ # spaces escaped. http://192.168.0.1\shello -# Mapped to "0xc0.0250.01" -http://\uff10\uff38\uff43\uff10\uff0e\uff10\uff12\uff15\uff10\uff0e\uff10\uff11 s:http p:/ h:0xc0.0250.01 +# Fullwidth and escaped UTF-8 fullwidth should still be treated as IP. +# These are "0Xc0.0250.01" in fullwidth. +http://\uff10\uff38\uff43\uff10\uff0e\uff10\uff12\uff15\uff10\uff0e\uff10\uff11 s:http p:/ h:192.168.0.1 # Broken IPv6 http://[google.com] + +# Misc Unicode +http://foo:\uD83D\uDCA9@example.com/bar s:http h:example.com p:/bar u:foo pass:%F0%9F%92%A9 + +# resolving a relative reference against an unknown scheme results in an error +x test:test diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/url/urltestparser.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/url/urltestparser.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/url/urltestparser.js 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/url/urltestparser.js 2014-11-26 21:45:59.000000000 +0000 @@ -1,6 +1,6 @@ function URLTestParser(input) { var relativeSchemes = ["ftp", "file", "gopher", "http", "https", "ws", "wss"], - tokenMap = { "\\": "\\", n: "\n", r: "\r", s: " ", t: "\t", f: "\f" } + tokenMap = { "\\": "\\", "#": "#", n: "\n", r: "\r", s: " ", t: "\t", f: "\f" } resultMap = { s: "scheme", u: "username", pass: "password", h: "host", port: "port", p: "path", q: "query", f: "fragment" }, results = [] function Test() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/vibration/pattern-array-with-0-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/vibration/pattern-array-with-0-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/vibration/pattern-array-with-0-manual.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/vibration/pattern-array-with-0-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,26 @@ + + +Vibration API: test a pattern array with 0ms vibration and still to vibrate() + + + + + +

Description

+

+ After hitting the button below, your device must vibrate continuously for about two seconds, once. +

+ +
+ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/vibration/simple-array-manual.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/vibration/simple-array-manual.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/vibration/simple-array-manual.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/vibration/simple-array-manual.html 2014-11-26 21:45:59.000000000 +0000 @@ -5,8 +5,6 @@ Vibration API: test a simple array parameter to vibrate() - -

Description

@@ -15,20 +13,11 @@

- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-after.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-after.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-after.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-after.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,420 @@ + + +AnimationNode after() method tests + + + + + + + + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-before.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-before.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-before.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-before.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,419 @@ + + +AnimationNode before() method tests + + + + + + + + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-remove.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-remove.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-remove.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-remove.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,240 @@ + + +AnimationNode remove() method tests + + + + + + + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-replace.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-replace.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-replace.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/animation-node-replace.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,445 @@ + + +AnimationNode replace() method tests + + + + + + + + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/idlharness.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/idlharness.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-node/idlharness.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-node/idlharness.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,54 @@ + + +AnimationNode IDL tests + + + + + + + +
+
+ + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-timeline/animation-timeline.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-timeline/animation-timeline.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-timeline/animation-timeline.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-timeline/animation-timeline.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ - - -Web Animations API: AnimationTimeline tests - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-timeline/idlharness.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-timeline/idlharness.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/animation-timeline/idlharness.html 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/animation-timeline/idlharness.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ - - -Web Animations API: AnimationTimeline tests - - - - -
- - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/README.md thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/README.md --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/README.md 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/README.md 2014-11-26 21:45:59.000000000 +0000 @@ -1,4 +1,4 @@ Web Animations Tests ==================== -Specification: http://dev.w3.org/fxtf/web-animations/ +Specification: http://w3c.github.io/web-animations/ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/testcommon.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/testcommon.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/web-animations/testcommon.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/web-animations/testcommon.js 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,58 @@ +/* +Distributed under both the W3C Test Suite License [1] and the W3C +3-clause BSD License [2]. To contribute to a W3C Test Suite, see the +policies and contribution forms [3]. + +[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license +[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license +[3] http://www.w3.org/2004/10/27-testcases + */ + +"use strict"; + +var ANIMATION_END_TIME = 1000; +var ANIMATION_TOP_DEFAULT = 300; +var ANIMATION_TOP_0 = 10; +var ANIMATION_TOP_0_5 = 100; +var ANIMATION_TOP_1 = 200; + +var KEYFRAMES = [ { + top : ANIMATION_TOP_0 + 'px', + offset : 0 +}, { + top : ANIMATION_TOP_0_5 + 'px', + offset : 1 / 2 +}, { + top : ANIMATION_TOP_1 + 'px', + offset : 1 +} ]; + +// creates new animation for given target +function newAnimation(animationTarget) { + animationTarget.style.top = ANIMATION_TOP_DEFAULT + 'px'; + return new Animation(animationTarget, KEYFRAMES, ANIMATION_END_TIME); +} + +// creates div element, appends it to the document body and +// add removing of the created element to test cleanup +function createDiv(test, doc) { + if (!doc) { + doc = document; + } + var div = doc.createElement('div'); + doc.body.appendChild(div); + test.add_cleanup(function() { + removeElement(div); + }); + return div; +} + +// Removes element +function removeElement(element) { + element.parentNode.removeChild(element); +} + +// Returns the type name of given object +function type(object) { + return Object.prototype.toString.call(object).slice(8, -1); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/base_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/base_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/base_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/base_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,13 +4,13 @@ import sys import unittest -from webserver import Httpd from network import get_lan_ip repo_root = os.path.abspath(os.path.join(__file__, "../..")) sys.path.insert(1, os.path.join(repo_root, "tools", "webdriver")) +sys.path.insert(1, os.path.join(repo_root, "tools", "wptserve")) +from wptserve import server from webdriver.driver import WebDriver -from webdriver import exceptions, wait class WebDriverBaseTest(unittest.TestCase): @@ -18,8 +18,9 @@ def setUpClass(cls): cls.driver = create_driver() - cls.webserver = Httpd(host=get_lan_ip()) + cls.webserver = server.WebTestHttpd(host=get_lan_ip()) cls.webserver.start() + cls.webserver.where_is = cls.webserver.get_url @classmethod def tearDownClass(cls): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/cookie/cookie_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/cookie/cookie_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/cookie/cookie_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/cookie/cookie_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,6 +4,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions class CookieTest(base_test.WebDriverBaseTest): @@ -44,7 +45,7 @@ self.driver.add_cookie({ 'name': invalid_name, 'value': value }) self.fail( 'should have thrown exceptions.' ) - except UnableToSetCookieException: + except exceptions.UnableToSetCookieException: pass except exceptions.InvalidCookieDomainException: pass diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/element_location/element_location_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/element_location/element_location_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/element_location/element_location_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/element_location/element_location_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -7,19 +7,14 @@ class ElementLocationTest(base_test.WebDriverBaseTest): - def test_find_element_by_id(self): - self.driver.get(self.webserver.where_is("element_location/res/elements.html")) - e = self.driver.find_element_by_id("id") - self.assertEquals("id", e.text) - def test_find_element_by_name(self): self.driver.get(self.webserver.where_is("element_location/res/elements.html")) - e = self.driver.find_element_by_name("name") + e = self.driver.find_element_by_css("*[name='name']") self.assertEquals("name", e.text) def test_find_element_by_css_selector(self): self.driver.get(self.webserver.where_is("element_location/res/elements.html")) - e = self.driver.find_element_by_css_selector("#id") + e = self.driver.find_element_by_css("#id") self.assertEquals("id", e.text) def test_find_element_by_link_text(self): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/element_state/visibility_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/element_state/visibility_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/element_state/visibility_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/element_state/visibility_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,6 +4,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions class NaturalNonVisibleElementsTest(base_test.WebDriverBaseTest): @@ -24,8 +25,8 @@ def test_zero_sized_element_is_shown_if_decendant_has_size(self): self.driver.get(self.webserver.where_is("element_state/res/zero-sized-element-with-sizable-decendant.html")) - parent = self.driver.find_element_by_id("parent") - child = self.driver.find_element_by_id("child") + parent = self.driver.find_element_by_css("#parent") + child = self.driver.find_element_by_css("#child") self.assertTrue(parent.is_displayed()) self.assertTrue(child.is_displayed()) @@ -53,7 +54,7 @@ children = self.driver.find_elements_by_css(".child") assert all(child.is_displayed() for child in children) - parent = self.driver.find_element_by_id("parent") + parent = self.driver.find_element_by_css("#parent") assert parent.is_displayed() def test_element_hidden_by_overflow_x_is_not_visible(self): @@ -65,8 +66,8 @@ for page in pages: self.driver.get(self.webserver.where_is(page)) - right = self.driver.find_element_by_id("right") - bottom_right = self.driver.find_element_by_id("bottom-right") + right = self.driver.find_element_by_css("#right") + bottom_right = self.driver.find_element_by_css("#bottom-right") self.assertFalse(right.is_displayed()) self.assertFalse(bottom_right.is_displayed()) @@ -80,8 +81,8 @@ for page in pages: self.driver.get(self.webserver.where_is(page)) - bottom = self.driver.find_element_by_id("bottom") - bottom_right = self.driver.find_element_by_id("bottom-right") + bottom = self.driver.find_element_by_css("#bottom") + bottom_right = self.driver.find_element_by_css("#bottom-right") self.assertFalse(bottom.is_displayed()) self.assertFalse(bottom_right.is_displayed()) @@ -113,21 +114,21 @@ def test_element_hidden_by_other_element(self): self.driver.get(self.webserver.where_is("element_state/res/element-hidden-by-other-element.html")) - overlay = self.driver.find_element_by_id("overlay") - hidden = self.driver.find_element_by_id("hidden") + overlay = self.driver.find_element_by_css("#overlay") + hidden = self.driver.find_element_by_css("#hidden") self.assertTrue(overlay.is_displayed()) self.assertFalse(hidden.is_displayed()) def test_element_partially_hidden_by_other_element(self): self.driver.get(self.webserver.where_is("element_state/res/element-partially-hidden-by-other-element.html")) - partial = self.driver.find_element_by_id("partial") + partial = self.driver.find_element_by_css("#partial") self.assertTrue(partial.is_displayed()) def test_element_hidden_by_z_index(self): self.driver.get(self.webserver.where_is("element_state/res/element-hidden-by-z-index.html")) - overlay = self.driver.find_element_by_id("overlay") - hidden = self.driver.find_element_by_id("hidden") + overlay = self.driver.find_element_by_css("#overlay") + hidden = self.driver.find_element_by_css("#hidden") self.assertTrue(overlay.is_displayed()) self.assertFalse(hidden.is_displayed()) @@ -139,8 +140,8 @@ def test_element_moved_behind_other_element_by_transform(self): self.driver.get(self.webserver.where_is("element_state/res/element-moved-behind-other-element-by-transform.html")) - overlay = self.driver.find_element_by_id("overlay") - hidden = self.driver.find_element_by_id("hidden") + overlay = self.driver.find_element_by_css("#overlay") + hidden = self.driver.find_element_by_css("#hidden") self.assertTrue(overlay.is_displayed()) self.assertFalse(hidden.is_displayed()) @@ -167,7 +168,7 @@ def test_element_with_same_color_as_parent_background(self): self.driver.get(self.webserver.where_is("element_state/res/element-with-same-color-as-parent-background.html")) - hidden = self.driver.find_element_by_id("hidden") + hidden = self.driver.find_element_by_css("#hidden") self.assertFalse(hidden.is_displayed()) @@ -203,35 +204,35 @@ def test_display_none_hides_child_node(self): self.driver.get(self.webserver.where_is("element_state/res/display-none-child.html")) - parent = self.driver.find_element_by_id("parent") - child = self.driver.find_element_by_id("child") + parent = self.driver.find_element_by_css("#parent") + child = self.driver.find_element_by_css("#child") self.assertFalse(parent.is_displayed()) self.assertFalse(child.is_displayed()) def test_display_none_hides_child_node_link(self): self.driver.get(self.webserver.where_is("element_state/res/display-none-child-link.html")) - child = self.driver.find_element_by_id("child") + child = self.driver.find_element_by_css("#child") self.assertFalse(child.is_displayed()) def test_display_none_hides_child_node_paragraph(self): self.driver.get(self.webserver.where_is("element_state/res/display-none-child-paragraph.html")) - child = self.driver.find_element_by_id("child") + child = self.driver.find_element_by_css("#child") self.assertFalse(child.is_displayed()) def test_display_none_on_parent_takes_presedence(self): self.driver.get(self.webserver.where_is("element_state/res/display-none-parent-presedence.html")) - child = self.driver.find_element_by_id("child") + child = self.driver.find_element_by_css("#child") self.assertFalse(child.is_displayed()) def test_display_none_on_parent_takes_presedence_over_visibility_visible(self): self.driver.get(self.webserver.where_is("element_state/res/display-none-parent-presedence-visibility.html")) - child = self.driver.find_element_by_id("child") + child = self.driver.find_element_by_css("#child") self.assertFalse(child.is_displayed()) def test_display_none_hidden_dynamically(self): self.driver.get(self.webserver.where_is("element_state/res/display-none-dynamic.html")) - hidden = self.driver.find_element_by_id("hidden") + hidden = self.driver.find_element_by_css("#hidden") self.assertFalse(hidden.is_displayed()) @@ -248,34 +249,34 @@ def test_visibility_hidden_hides_child_node(self): self.driver.get(self.webserver.where_is("element_state/res/visibility-child.html")) - parent = self.driver.find_element_by_id("parent") - child = self.driver.find_element_by_id("child") + parent = self.driver.find_element_by_css("#parent") + child = self.driver.find_element_by_css("#child") self.assertFalse(parent.is_displayed()) self.assertFalse(child.is_displayed()) def test_visibility_hidden_hides_child_node_link(self): self.driver.get(self.webserver.where_is("element_state/res/visibility-child-link.html")) - parent = self.driver.find_element_by_id("parent") - child = self.driver.find_element_by_id("child") + parent = self.driver.find_element_by_css("#parent") + child = self.driver.find_element_by_css("#child") self.assertFalse(parent.is_displayed()) self.assertFalse(child.is_displayed()) def test_visibility_hidden_hides_child_node_paragraph(self): self.driver.get(self.webserver.where_is("element_state/res/visibility-child-paragraph.html")) - parent = self.driver.find_element_by_id("parent") - child = self.driver.find_element_by_id("child") + parent = self.driver.find_element_by_css("#parent") + child = self.driver.find_element_by_css("#child") self.assertFalse(parent.is_displayed()) self.assertFalse(child.is_displayed()) - def test_visibility_hidden_on_child_takes_presedence(self): + def test_visibility_hidden_on_child_takes_precedence(self): self.driver.get(self.webserver.where_is("element_state/res/visibility-child-presedence.html")) - child = self.driver.find_element_by_id("child") + child = self.driver.find_element_by_css("#child") self.assertTrue(child.is_displayed()) - def test_visibility_hidden_on_parent_takes_presedence_over_display_block(self): + def test_visibility_hidden_on_parent_takes_precedence_over_display_block(self): pass def test_visibility_hidden_set_dynamically(self): @@ -283,12 +284,12 @@ def test_should_show_element_not_visible_with_hidden_attribute(self): self.driver.get(self.webserver.where_is("element_state/res/hidden.html")) - singleHidden = self.driver.find_element('id', 'singleHidden') + singleHidden = self.driver.find_element_by_css('#singleHidden') self.assertFalse(singleHidden.is_displayed()) def test_should_show_element_not_visible_when_parent_element_has_hidden_attribute(self): self.driver.get(self.webserver.where_is("element_state/res/hidden.html")) - child = self.driver.find_element('id', 'child') + child = self.driver.find_element_by_css('#child') self.assertFalse(child.is_displayed()) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/modal/alerts_quit_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/modal/alerts_quit_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/modal/alerts_quit_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/modal/alerts_quit_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,6 +4,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions, wait class AlertsQuitTest(base_test.WebDriverBaseTest): @@ -12,7 +13,7 @@ self.driver.get(self.webserver.where_is('modal/res/alerts.html')) def test_can_quit_when_an_alert_is_present(self): - self.driver.find_element_by_id('alert').click() + self.driver.find_element_by_css('#alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) self.driver.quit() with self.assertRaises(Exception): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/modal/alerts_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/modal/alerts_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/modal/alerts_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/modal/alerts_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,6 +4,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions, wait class AlertsTest(base_test.WebDriverBaseTest): @@ -19,39 +20,39 @@ # Alerts def test_should_allow_user_to_accept_an_alert(self): - self.driver.find_element_by_id('alert').click() + self.driver.find_element_by_css('#alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() self.driver.get_current_url() def test_should_allow_user_to_accept_an_alert_with_no_text(self): - self.driver.find_element_by_id('empty-alert').click() + self.driver.find_element_by_css('#empty-alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() self.driver.get_current_url() def test_should_allow_user_to_dismiss_an_alert(self): - self.driver.find_element_by_id('alert').click() + self.driver.find_element_by_css('#alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.dismiss() self.driver.get_current_url() def test_should_allow_user_to_get_text_of_an_alert(self): - self.driver.find_element_by_id('alert').click() + self.driver.find_element_by_css('#alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) value = alert.get_text() alert.accept() self.assertEquals('cheese', value) def test_setting_the_value_of_an_alert_throws(self): - self.driver.find_element_by_id('alert').click() + self.driver.find_element_by_css('#alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) with self.assertRaises(exceptions.ElementNotVisibleException): alert.send_keys('cheese') alert.accept() def test_alert_should_not_allow_additional_commands_if_dismissed(self): - self.driver.find_element_by_id('alert').click() + self.driver.find_element_by_css('#alert').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() with self.assertRaises(exceptions.NoSuchAlertException): @@ -59,79 +60,79 @@ # Prompts def test_should_allow_user_to_accept_a_prompt(self): - self.driver.find_element_by_id('prompt').click() + self.driver.find_element_by_css('#prompt').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == '') + self.wait.until(lambda x: x.find_element_by_css('#text').text == '') def test_should_allow_user_to_dismiss_a_prompt(self): - self.driver.find_element_by_id('prompt').click() + self.driver.find_element_by_css('#prompt').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.dismiss() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == 'null') + self.wait.until(lambda x: x.find_element_by_css('#text').text == 'null') def test_should_allow_user_to_set_the_value_of_a_prompt(self): - self.driver.find_element_by_id('prompt').click() + self.driver.find_element_by_css('#prompt').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.send_keys('cheese') alert.accept() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == 'cheese') + self.wait.until(lambda x: x.find_element_by_css('#text').text == 'cheese') def test_should_allow_user_to_get_text_of_a_prompt(self): - self.driver.find_element_by_id('prompt').click() + self.driver.find_element_by_css('#prompt').click() alert = self.wait.until(lambda x: x.switch_to_alert()) value = alert.get_text() alert.accept() self.assertEquals('Enter something', value) def test_prompt_should_not_allow_additional_commands_if_dismissed(self): - self.driver.find_element_by_id('prompt').click() + self.driver.find_element_by_css('#prompt').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() with self.assertRaises(exceptions.NoSuchAlertException): alert.get_text() def test_prompt_should_use_default_value_if_no_keys_sent(self): - self.driver.find_element_by_id('prompt-with-default').click() + self.driver.find_element_by_css('#prompt-with-default').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == 'This is a default value') + self.wait.until(lambda x: x.find_element_by_css('#text').text == 'This is a default value') def test_prompt_should_have_null_value_if_dismissed(self): - self.driver.find_element_by_id('prompt-with-default').click() + self.driver.find_element_by_css('#prompt-with-default').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.dismiss() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == 'null') + self.wait.until(lambda x: x.find_element_by_css('#text').text == 'null') # Confirmations def test_should_allow_user_to_accept_a_confirm(self): - self.driver.find_element_by_id('confirm').click() + self.driver.find_element_by_css('#confirm').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == 'true') + self.wait.until(lambda x: x.find_element_by_css('#text').text == 'true') def test_should_allow_user_to_dismiss_a_confirm(self): - self.driver.find_element_by_id('confirm').click() + self.driver.find_element_by_css('#confirm').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.dismiss() - self.wait.until(lambda x: x.find_element_by_id('text').get_text() == 'false') + self.wait.until(lambda x: x.find_element_by_css('#text').text == 'false') def test_setting_the_value_of_a_confirm_throws(self): - self.driver.find_element_by_id('confirm').click() + self.driver.find_element_by_css('#confirm').click() alert = self.wait.until(lambda x: x.switch_to_alert()) with self.assertRaises(exceptions.ElementNotVisibleException): alert.send_keys('cheese') alert.accept() def test_should_allow_user_to_get_text_of_a_confirm(self): - self.driver.find_element_by_id('confirm').click() + self.driver.find_element_by_css('#confirm').click() alert = self.wait.until(lambda x: x.switch_to_alert()) value = alert.get_text() alert.accept() self.assertEquals('cheese', value) def test_confirm_should_not_allow_additional_commands_if_dismissed(self): - self.driver.find_element_by_id('confirm').click() + self.driver.find_element_by_css('#confirm').click() alert = self.wait.until(lambda x: x.switch_to_alert()) alert.accept() with self.assertRaises(exceptions.NoSuchAlertException): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/auth_tests.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/auth_tests.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/auth_tests.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/auth_tests.py 2014-11-26 21:45:59.000000000 +0000 @@ -5,8 +5,10 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test -from webserver import Httpd - +from webdriver import exceptions +from wptserve import server +from wptserve.router import any_method +from wptserve.handlers import basic_auth_handler class WebDriverAuthTest(unittest.TestCase): @@ -15,16 +17,7 @@ @classmethod def setUpClass(cls): cls.driver = base_test.create_driver() - - def basic_response_func( request, *args ): - return (401, {"WWW-Authenticate" : "Basic"}, None) - - basic_auth_handler = { 'method': 'GET', - 'path' : '/navigation/auth_required_basic', - 'function' : basic_response_func } - urlhandlers = [ basic_auth_handler ] - - cls.webserver = Httpd( urlhandlers=urlhandlers ) + cls.webserver = server.WebTestHttpd(routes=[(any_method, "*", basic_auth_handler)]) cls.webserver.start() @classmethod @@ -34,7 +27,7 @@ # Test that when 401 is seen by browser, a WebDriver response is still sent def test_response_401_auth_basic(self): - page = self.webserver.where_is('navigation/auth_required_basic') + page = self.webserver.get_url('navigation/res/authenticated.html') self.driver.set_page_load_timeout(5) try: self.driver.get( page ) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/forward.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/forward.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/forward.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/forward.py 2014-11-26 21:45:59.000000000 +0000 @@ -11,12 +11,12 @@ def test_forward(self): self.driver.get(self.webserver.where_is('navigation/res/forwardStart.html')) self.driver.get(self.webserver.where_is('navigation/res/forwardNext.html')) - nextbody = self.driver.find_element_by_css("body").get_text() + nextbody = self.driver.find_element_by_css("body").text self.driver.go_back() - currbody = self.driver.find_element_by_css("body").get_text() + currbody = self.driver.find_element_by_css("body").text self.assertNotEqual(nextbody, currbody) self.driver.go_forward() - currbody = self.driver.find_element_by_css("body").get_text() + currbody = self.driver.find_element_by_css("body").text self.assertEqual(nextbody, currbody) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/forwardToNothing.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/forwardToNothing.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/forwardToNothing.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/forwardToNothing.py 2014-11-26 21:45:59.000000000 +0000 @@ -10,9 +10,9 @@ # Get a static page that must be the same upon refresh def test_forwardToNothing(self): self.driver.get(self.webserver.where_is('navigation/forwardStart.html')) - body = self.driver.find_element_by_css("body").get_text() + body = self.driver.find_element_by_css("body").text self.driver.go_forward() - currbody = self.driver.find_element_by_css("body").get_text() + currbody = self.driver.find_element_by_css("body").text self.assertEqual(body, currbody) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/refresh-page.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/refresh-page.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/refresh-page.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/refresh-page.py 2014-11-26 21:45:59.000000000 +0000 @@ -10,16 +10,16 @@ # Get a static page that must be the same upon refresh def test_refreshPage(self): self.driver.get(self.webserver.where_is('navigation/res/refreshPageStatic.html')) - body = self.driver.find_element_by_css("body").get_text() + body = self.driver.find_element_by_css("body").text self.driver.execute_script("document.getElementById('body').innerHTML=''") self.driver.refresh() - newbody = self.driver.find_element_by_css("body").get_text() + newbody = self.driver.find_element_by_css("body").text self.assertEqual(body, newbody) self.driver.get(self.webserver.where_is('navigation/res/refreshPageDynamic.html')) - body = self.driver.find_element_by_css("body").get_text() + body = self.driver.find_element_by_css("body").text self.driver.refresh() - newbody = self.driver.find_element_by_css("body").get_text() + newbody = self.driver.find_element_by_css("body").text self.assertNotEqual(body, newbody) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/res/authenticated.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/res/authenticated.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/navigation/res/authenticated.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/navigation/res/authenticated.html 2014-11-26 21:45:59.000000000 +0000 @@ -0,0 +1,5 @@ + + + +authentication successful +

You're in!

\ No newline at end of file diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/README.md thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/README.md --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/README.md 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/README.md 2014-11-26 21:45:59.000000000 +0000 @@ -7,24 +7,9 @@ ## How to run the tests -1. It is highly recommended that you use a virtual Python environment. - This allows you to safely make changes to your Python environment - for WebDriver tests without affecting other software projects on - your system. - Install it using either ` easy_install virtualenv`, ` pip - install virtualenv`, or ` apt-get install python-virtualenv` -2. Create and enter the directory for your Python virtual environment. This - directory can be anywhere. It is recommended that you keep it separate - from the webdriver tests folder, to avoid confusion with source control -2a. Go to the directory where you store Python virtual environments. - For example `cd ~; mkdir python-virtualenv; cd python-virtualenv` -2b. Create a virtual env configuration and directory: `virtualenv webdriver-tests` -2c. Enter the directory: `cd webdriver-tests` -3. `source bin/activate` to activate the local Python installation -4. Install Selenium: `pip install selenium` or `easy_install selenium` -5. Go to the WebDriver tests: `cd _WEBDRIVER_TEST_ROOT_` -6. Run the tests: `python runtests.py` -7. Run the test against a different config specified in webdriver.cfg: +1. Go to the WebDriver tests: `cd _WEBDRIVER_TEST_ROOT_` +2. Run the tests: `python runtests.py` +3. Run the test against a different config specified in webdriver.cfg: `WD_BROWSER=chrome python runtests.py` To be run a specific test file you can just run `python test_file.py` diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/timeouts/implicit_waits_tests.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/timeouts/implicit_waits_tests.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/timeouts/implicit_waits_tests.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/timeouts/implicit_waits_tests.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,6 +4,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions class ImplicitWaitsTests(base_test.WebDriverBaseTest): @@ -11,15 +12,15 @@ self.driver.get(self.webserver.where_is('timeouts/res/implicit_waits_tests.html')) def test_find_element_by_id(self): - add = self.driver.find_element_by_id("adder") - self.driver.implicitly_wait(3) + add = self.driver.find_element_by_css("#adder") + self.driver.set_implicit_timeout(3) add.click() - self.driver.find_element_by_id("box0") # All is well if this doesn't throw. + self.driver.find_element_by_css("#box0") # All is well if this doesn't throw. def test_should_still_fail_to_find_an_element_when_implicit_waits_are_enabled(self): - self.driver.implicitly_wait(0.5) + self.driver.set_implicit_timeout(0.5) try: - self.driver.find_element_by_id("box0") + self.driver.find_element_by_css("#box0") self.fail("Expected NoSuchElementException to have been thrown") except exceptions.NoSuchElementException as e: pass @@ -27,10 +28,10 @@ self.fail("Expected NoSuchElementException but got " + str(e)) def test_should_return_after_first_attempt_to_find_one_after_disabling_implicit_waits(self): - self.driver.implicitly_wait(3) - self.driver.implicitly_wait(0) + self.driver.set_implicit_timeout(3) + self.driver.set_implicit_timeout(0) try: - self.driver.find_element_by_id("box0") + self.driver.find_element_by_css("#box0") self.fail("Expected NoSuchElementException to have been thrown") except exceptions.NoSuchElementException as e: pass @@ -38,24 +39,24 @@ self.fail("Expected NoSuchElementException but got " + str(e)) def test_should_implicitly_wait_until_at_least_one_element_is_found_when_searching_for_many(self): - add = self.driver.find_element_by_id("adder") - self.driver.implicitly_wait(2) + add = self.driver.find_element_by_css("#adder") + self.driver.set_implicit_timeout(2) add.click() add.click() - elements = self.driver.find_elements_by_class_name("redbox") + elements = self.driver.find_elements_by_css(".redbox") self.assertTrue(len(elements) >= 1) def test_should_still_fail_to_find_an_element_by_class_when_implicit_waits_are_enabled(self): - self.driver.implicitly_wait(0.5) - elements = self.driver.find_elements_by_class_name("redbox") + self.driver.set_implicit_timeout(0.5) + elements = self.driver.find_elements_by_css(".redbox") self.assertEqual(0, len(elements)) def test_should_return_after_first_attempt_to_find_many_after_disabling_implicit_waits(self): - add = self.driver.find_element_by_id("adder") - self.driver.implicitly_wait(1.1) - self.driver.implicitly_wait(0) + add = self.driver.find_element_by_css("#adder") + self.driver.set_implicit_timeout(1.1) + self.driver.set_implicit_timeout(0) add.click() - elements = self.driver.find_elements_by_class_name("redbox") + elements = self.driver.find_elements_by_css(".redbox") self.assertEqual(0, len(elements)) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/timeouts/page_load_timeouts_tests.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/timeouts/page_load_timeouts_tests.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/timeouts/page_load_timeouts_tests.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/timeouts/page_load_timeouts_tests.py 2014-11-26 21:45:59.000000000 +0000 @@ -4,6 +4,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions class PageLoadTimeoutTest(base_test.WebDriverBaseTest): diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/user_input/clear_test.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/user_input/clear_test.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/user_input/clear_test.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/user_input/clear_test.py 2014-11-26 21:45:59.000000000 +0000 @@ -6,44 +6,45 @@ sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../.."))) import base_test +from webdriver import exceptions class ElementClearTest(base_test.WebDriverBaseTest): def test_writable_text_input_element_should_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_writable_input_page.html")) - e = self.driver.find_element_by_id("writableTextInput") + e = self.driver.find_element_by_css("#writableTextInput") e.clear() self.assertEquals("", e.get_attribute("value")) def test_disabled_text_input_element_should_not_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_disabled_input_page.html")) - e = self.driver.find_element_by_id("disabledTextInput") + e = self.driver.find_element_by_css("#disabledTextInput") self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear()) def test_read_only_text_input_element_should_not_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_readonly_input_page.html")) - e = self.driver.find_element_by_id("readOnlyTextInput") + e = self.driver.find_element_by_css("#readOnlyTextInput") self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear()) def test_writable_text_area_element_should_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_writable_textarea_page.html")) - e = self.driver.find_element_by_id("writableTextArea") + e = self.driver.find_element_by_css("#writableTextArea") e.clear() self.assertEquals("", e.get_attribute("value")) def test_disabled_text_area_element_should_not_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_disabled_textarea_page.html")) - e = self.driver.find_element_by_id("disabledTextArea") + e = self.driver.find_element_by_css("#disabledTextArea") self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear()) def test_read_only_text_input_element_should_not_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_readonly_textarea_page.html")) - e = self.driver.find_element_by_id("readOnlyTextArea") + e = self.driver.find_element_by_css("#readOnlyTextArea") self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear()) def test_content_editable_area_should_clear(self): self.driver.get(self.webserver.where_is("user_input/res/element_clear_contenteditable_page.html")) - e = self.driver.find_element_by_id("contentEditableElement") + e = self.driver.find_element_by_css("#contentEditableElement") e.clear() self.assertEquals("", e.text) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/webdriver.cfg thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/webdriver.cfg --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/webdriver.cfg 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/webdriver.cfg 2014-11-26 21:45:59.000000000 +0000 @@ -24,3 +24,8 @@ [ios-driver] capabilities: {"browserName": "iphone"} mode: compatibility + +[blackberry] +url: http://169.254.0.1:1338 +capabilities: {"browserName": "blackberry"} +mode: compatibility diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/webserver.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/webserver.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/webdriver/webserver.py 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/webdriver/webserver.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,276 +0,0 @@ -#!/usr/bin/env python - -# 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/. - -import BaseHTTPServer -import SimpleHTTPServer -import errno -import logging -import threading -import posixpath -import socket -import sys -import os -import urllib -import urlparse -import re -import time -from SocketServer import ThreadingMixIn - -class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): - allow_reuse_address = True - acceptable_errors = (errno.EPIPE, errno.ECONNABORTED) - - def handle_error(self, request, client_address): - error = sys.exc_value - - if ((isinstance(error, socket.error) and - isinstance(error.args, tuple) and - error.args[0] in self.acceptable_errors) - or - (isinstance(error, IOError) and - error.errno in self.acceptable_errors)): - pass # remote hang up before the result is sent - else: - logging.error(error) - - -class Request(object): - """Details of a request.""" - - # attributes from urlsplit that this class also sets - uri_attrs = ('scheme', 'netloc', 'path', 'query', 'fragment') - - def __init__(self, uri, headers, rfile=None): - self.uri = uri - self.headers = headers - parsed = urlparse.urlsplit(uri) - for i, attr in enumerate(self.uri_attrs): - setattr(self, attr, parsed[i]) - try: - body_len = int(self.headers.get('Content-length', 0)) - except ValueError: - body_len = 0 - if body_len and rfile: - self.body = rfile.read(body_len) - else: - self.body = None - - -class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): - - docroot = os.getcwd() # current working directory at time of import - proxy_host_dirs = False - request_log = [] - log_requests = False - request = None - - def _try_handler(self, method): - if self.log_requests: - self.request_log.append({ 'method': method, - 'path': self.request.path, - 'time': time.time() }) - - handlers = [handler for handler in self.urlhandlers - if handler['method'] == method] - for handler in handlers: - m = re.match(handler['path'], self.request.path) - if m: - (response_code, headerdict, data) = \ - handler['function'](self.request, *m.groups()) - self.send_response(response_code) - for (keyword, value) in headerdict.iteritems(): - self.send_header(keyword, value) - self.end_headers() - self.wfile.write(data) - - return True - - return False - - def parse_request(self): - retval = SimpleHTTPServer.SimpleHTTPRequestHandler.parse_request(self) - self.request = Request(self.path, self.headers, self.rfile) - return retval - - def do_GET(self): - if not self._try_handler('GET'): - if self.path == '/navigation/redirect': - self.send_response(301) - self.send_header('Location', '/navigation/res/empty.html') - self.end_headers() - elif self.docroot: - # don't include query string and fragment, and prepend - # host directory if required. - if self.request.netloc and self.proxy_host_dirs: - self.path = '/' + self.request.netloc + \ - self.request.path - else: - self.path = self.request.path - SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) - else: - self.send_response(404) - self.end_headers() - self.wfile.write('') - - def do_POST(self): - # if we don't have a match, we always fall through to 404 (this may - # not be "technically" correct if we have a local file at the same - # path as the resource but... meh) - if not self._try_handler('POST'): - self.send_response(404) - self.end_headers() - self.wfile.write('') - - def do_DEL(self): - # if we don't have a match, we always fall through to 404 (this may - # not be "technically" correct if we have a local file at the same - # path as the resource but... meh) - if not self._try_handler('DEL'): - self.send_response(404) - self.end_headers() - self.wfile.write('') - - def translate_path(self, path): - # this is taken from SimpleHTTPRequestHandler.translate_path(), - # except we serve from self.docroot instead of os.getcwd(), and - # parse_request()/do_GET() have already stripped the query string and - # fragment and mangled the path for proxying, if required. - path = posixpath.normpath(urllib.unquote(self.path)) - words = path.split('/') - words = filter(None, words) - path = self.docroot - for word in words: - drive, word = os.path.splitdrive(word) - head, word = os.path.split(word) - if word in (os.curdir, os.pardir): continue - path = os.path.join(path, word) - return path - - - # I found on my local network that calls to this were timing out - # I believe all of these calls are from log_message - def address_string(self): - return "a.b.c.d" - - # This produces a LOT of noise - def log_message(self, format, *args): - pass - - -class Httpd(object): - """ - Very basic HTTP server class. Takes a docroot (path on the filesystem) - and a set of urlhandler dictionaries of the form: - - { - 'method': HTTP method (string): GET, POST, or DEL, - 'path': PATH_INFO (regular expression string), - 'function': function of form fn(arg1, arg2, arg3, ..., request) - } - - and serves HTTP. For each request, MozHttpd will either return a file - off the docroot, or dispatch to a handler function (if both path and - method match). - - Note that one of docroot or urlhandlers may be None (in which case no - local files or handlers, respectively, will be used). If both docroot or - urlhandlers are None then MozHttpd will default to serving just the local - directory. - - MozHttpd also handles proxy requests (i.e. with a full URI on the request - line). By default files are served from docroot according to the request - URI's path component, but if proxy_host_dirs is True, files are served - from //. - - For example, the request "GET http://foo.bar/dir/file.html" would - (assuming no handlers match) serve /dir/file.html if - proxy_host_dirs is False, or /foo.bar/dir/file.html if it is - True. - """ - - def __init__(self, host="127.0.0.1", port=8888, docroot=None, - urlhandlers=None, proxy_host_dirs=False, log_requests=False): - self.host = host - self.port = int(port) - self.docroot = docroot - if not urlhandlers and not docroot: - self.docroot = os.getcwd() - self.proxy_host_dirs = proxy_host_dirs - self.httpd = None - self.urlhandlers = urlhandlers or [] - self.log_requests = log_requests - self.request_log = [] - - class RequestHandlerInstance(RequestHandler): - docroot = self.docroot - urlhandlers = self.urlhandlers - proxy_host_dirs = self.proxy_host_dirs - request_log = self.request_log - log_requests = self.log_requests - - self.handler_class = RequestHandlerInstance - - def start(self, block=False): - """ - Start the server. If block is True, the call will not return. - If block is False, the server will be started on a separate thread that - can be terminated by a call to .stop() - """ - self.httpd = EasyServer((self.host, self.port), self.handler_class) - if block: - self.httpd.serve_forever() - else: - self.server = threading.Thread(target=self.httpd.serve_forever) - self.server.setDaemon(True) # don't hang on exit - self.server.start() - - def stop(self): - if self.httpd: - ### FIXME: There is no shutdown() method in Python 2.4... - try: - self.httpd.shutdown() - except AttributeError: - pass - self.httpd = None - - __del__ = stop - - def where_is(self, path): - return "http://%s:%d/%s" % (self.host, self.port, path) - - -def main(args=sys.argv[1:]): - - # parse command line options - from optparse import OptionParser - parser = OptionParser() - parser.add_option('-p', '--port', dest='port', - type="int", default=8888, - help="port to run the server on [DEFAULT: %default]") - parser.add_option('-H', '--host', dest='host', - default='127.0.0.1', - help="host [DEFAULT: %default]") - parser.add_option('-i', '--external-ip', action="store_true", - dest='external_ip', default=False, - help="find and use external ip for host") - parser.add_option('-d', '--docroot', dest='docroot', - default=os.getcwd(), - help="directory to serve files from [DEFAULT: %default]") - options, args = parser.parse_args(args) - if args: - parser.error("mozhttpd does not take any arguments") - - host = options.host - - # create the server - server = Httpd(host=host, port=options.port, docroot=options.docroot) - - print "Serving '%s' at %s:%s" % (server.docroot, server.host, server.port) - server.start(block=True) - -if __name__ == '__main__': - main() - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/websockets/Close-reason-unpaired-surrogates.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/websockets/Close-reason-unpaired-surrogates.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/websockets/Close-reason-unpaired-surrogates.htm 2014-11-14 09:37:24.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/websockets/Close-reason-unpaired-surrogates.htm 2014-11-26 21:45:59.000000000 +0000 @@ -15,6 +15,7 @@ var wsocket = CreateWebSocket(false, false, false); var isOpenCalled = false; + var replacementChar = "\uFFFD"; var reason = "\uD807"; wsocket.addEventListener('open', testOpen.step_func(function (evt) { @@ -25,6 +26,7 @@ wsocket.addEventListener('close', testClose.step_func(function (evt) { assert_true(isOpenCalled, "WebSocket connection should be opened"); + assert_equals(evt.reason, replacementChar, "reason replaced with replacement character"); testClose.done(); }), true); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm 2014-11-14 09:37:25.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm 2014-11-26 21:45:59.000000000 +0000 @@ -15,6 +15,7 @@ var wsocket = CreateWebSocket(true, false, false); var isOpenCalled = false; + var replacementChar = "\uFFFD"; var reason = "\uD807"; wsocket.addEventListener('open', testOpen.step_func(function (evt) { @@ -25,6 +26,7 @@ wsocket.addEventListener('close', testClose.step_func(function (evt) { assert_true(isOpenCalled, "WebSocket connection should be opened"); + assert_equals(evt.reason, replacementChar, "reason replaced with replacement character"); testClose.done(); }), true); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html 2014-11-26 21:46:00.000000000 +0000 @@ -1,6 +1,6 @@ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html 2014-11-26 21:46:00.000000000 +0000 @@ -2,7 +2,7 @@ try { postMessage(1, null); } catch(e) { - postMessage(''+e); + postMessage(e instanceof TypeError); } /* --> @@ -15,11 +15,11 @@ (async_test()).step(function() { var worker = new Worker('#'); worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 1); + assert_true(e.data); this.done(); }); }); \ No newline at end of file +//--> diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,25 @@ + + +Using undefined in postMessage's second argument + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/common.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/common.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/common.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/common.js 2014-11-26 21:46:00.000000000 +0000 @@ -25,7 +25,7 @@ if (test_obj) test_obj.done(); } -function compare_Array(callback) { +function compare_Array(callback, callback_is_async) { return function(actual, input, test_obj) { if (typeof actual === 'string') assert_unreached(actual); @@ -33,12 +33,12 @@ assert_not_equals(actual, input); assert_equals(actual.length, input.length, 'length'); callback(actual, input); - if (test_obj) + if (test_obj && !callback_is_async) test_obj.done(); } } -function compare_Object(callback) { +function compare_Object(callback, callback_is_async) { return function(actual, input, test_obj) { if (typeof actual === 'string') assert_unreached(actual); @@ -46,15 +46,15 @@ assert_false(actual instanceof Array, 'instanceof Array'); assert_not_equals(actual, input); callback(actual, input); - if (test_obj) + if (test_obj && !callback_is_async) test_obj.done(); } } -function enumerate_props(compare_func) { +function enumerate_props(compare_func, test_obj) { return function(actual, input) { for (var x in input) { - compare_func(actual[x], input[x]); + compare_func(actual[x], input[x], test_obj); } }; } @@ -339,41 +339,41 @@ check('Blob NUL', func_Blob_NUL, compare_Blob); async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Array Blob object, Blob basic'); async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)'); async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)'); async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Array Blob object, Blob paired surrogates (invalid utf-8)'); async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Array Blob object, Blob empty'); async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Array Blob object, Blob NUL'); async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Object Blob object, Blob basic'); async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)'); async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)'); async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Object Blob object, Blob paired surrogates (invalid utf-8)'); async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Object Blob object, Blob empty'); async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob)), test_obj); + check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); }, 'Object Blob object, Blob NUL'); function compare_File(actual, input, test_obj) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/worker-common.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/worker-common.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/worker-common.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/semantics/structured-clone/worker-common.js 2014-11-26 21:46:00.000000000 +0000 @@ -9,8 +9,9 @@ return true; } -function check_Blob(msg, input, port, expect_File) { +function check_Blob(msg, input, port, expect_File, orig_input) { expect_File = !!expect_File; + orig_input = orig_input || input; try { var expected; switch (msg) { @@ -64,7 +65,7 @@ check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']') } if (log.length === 0) { - port.postMessage(input); + port.postMessage(orig_input); } else { port.postMessage('FAIL '+log); } @@ -724,7 +725,7 @@ case 'Array Blob object, Blob NUL': if (check_true(input instanceof Array, 'input instanceof Array') && check_true(input.length === 1, 'input.length === 1')) { - check_Blob(msg.substr('Array Blob object, '.length), input[0], port); + check_Blob(msg.substr('Array Blob object, '.length), input[0], port, false, input); // no postMessage or close here, check_Blob takes care of that } break; @@ -742,7 +743,7 @@ i++; } if (check_true(i === 1, 'i === 1')) { - check_Blob(msg.substr('Object Blob object, '.length), input['x'], port); + check_Blob(msg.substr('Object Blob object, '.length), input['x'], port, false, input); // no postMessage or close here, check_Blob takes care of that } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/Worker_cross_origin_security_err.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/Worker_cross_origin_security_err.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/Worker_cross_origin_security_err.htm 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/Worker_cross_origin_security_err.htm 2014-11-26 21:46:00.000000000 +0000 @@ -8,15 +8,15 @@
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/Worker_dispatchEvent_ErrorEvent.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/Worker_dispatchEvent_ErrorEvent.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/workers/Worker_dispatchEvent_ErrorEvent.htm 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/workers/Worker_dispatchEvent_ErrorEvent.htm 2014-11-26 21:46:00.000000000 +0000 @@ -1,44 +1,55 @@ - ErrorEvent.initErrorEvent() and Worker.dispatchEvent() + ErrorEvent and Worker.dispatchEvent()
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-receive.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-receive.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-receive.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-receive.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: abort() after successful receive should not fire "abort" event - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-send.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-send.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-send.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-send.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,14 +4,14 @@ XMLHttpRequest: abort() after send() - - - - - - - - + + + + + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-stop.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-stop.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-stop.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-stop.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: abort event should fire when stop() method is used - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-timeout.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-timeout.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-timeout.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-after-timeout.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: abort() after a timeout should not fire "abort" event - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-done.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-done.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-done.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-done.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: abort() during DONE - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-open.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-open.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-open.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-open.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: abort() during OPEN - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-unsent.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-unsent.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-unsent.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-unsent.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: abort() during UNSENT - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-upload.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-upload.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-upload.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-during-upload.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: abort() while sending data - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-abort.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-abort.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-abort.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-abort.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,7 +1,7 @@ - + XMLHttpRequest: The abort() method: do not fire abort event in OPENED state when send() flag is unset. send() throws after abort(). diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-listeners.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-listeners.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-listeners.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-listeners.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: abort() should not reset event listeners - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-loadend.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-loadend.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-loadend.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-loadend.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,7 +1,7 @@ - + XMLHttpRequest: The abort() method: Fire a progress event named loadend diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-order.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-order.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-order.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-event-order.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,7 +1,7 @@  - + XMLHttpRequest: The abort() method: abort and loadend events diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-abort.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-abort.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-abort.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-abort.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,7 +1,7 @@  - + XMLHttpRequest: The abort() method: Fire a progress event named abort on the XMLHttpRequestUpload object diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-loadend.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-loadend.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-loadend.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/abort-upload-event-loadend.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,7 +1,7 @@  - + XMLHttpRequest: The abort() method: Fire a progress event named loadend on the XMLHttpRequestUpload object diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/data-uri.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/data-uri.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/data-uri.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/data-uri.htm 2014-11-26 21:45:53.000000000 +0000 @@ -3,8 +3,8 @@ XMLHttpRequest: data uri - - + +
- - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-loadend.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-loadend.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-loadend.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-loadend.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,11 +4,11 @@ XMLHttpRequest: loadend event - - - - - + + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-load.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-load.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-load.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-load.htm 2014-11-26 21:45:53.000000000 +0000 @@ -3,10 +3,10 @@ XMLHttpRequest: The send() method: Fire an event named load (synchronous flag is unset) - - - - + + + +
- - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-progress.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-progress.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-progress.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-progress.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,11 +4,11 @@ XMLHttpRequest: The send() method: Fire a progress event named progress (synchronous flag is unset) - - - - - + + + + +
- - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-timeout.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-timeout.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-timeout.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-timeout.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,11 +4,11 @@ XMLHttpRequest: timeout event - - - - - + + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm 2014-11-26 21:45:53.000000000 +0000 @@ -0,0 +1,26 @@ + + + +XMLHttpRequest: upload progress event for cross-origin requests + + + + + + + +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/event-upload-progress.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,10 +4,10 @@ XMLHttpRequest: upload progress event - - - - + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/formdata-blob.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/formdata-blob.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/formdata-blob.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/formdata-blob.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,11 +4,11 @@ XMLHttpRequest: upload formdata with blob - - - - - + + + + +
- - - - + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-cookies.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-cookies.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-cookies.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-cookies.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getAllResponseHeaders() excludes cookies - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-status.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-status.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-status.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getallresponseheaders-status.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getAllResponseHeaders() excludes status - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-case-insensitive.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-case-insensitive.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-case-insensitive.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-case-insensitive.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() case-insensitive matching - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() and HTTP trailer - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() custom/non-existent headers and cookies - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-error-state.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-error-state.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-error-state.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-error-state.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() in error state (failing cross-origin test) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-server-date.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-server-date.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-server-date.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-server-date.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() server and date - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-special-characters.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-special-characters.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-special-characters.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-special-characters.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() funny characters - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: getResponseHeader() in unsent, opened states - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/interfaces.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/interfaces.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/interfaces.html 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/interfaces.html 2014-11-26 21:45:53.000000000 +0000 @@ -10,9 +10,42 @@
@@ -22,7 +55,8 @@ typedef EventHandlerNonNull? EventHandler; - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-after-setrequestheader.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-after-setrequestheader.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-after-setrequestheader.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-after-setrequestheader.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() after setRequestHeader() - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-bogus.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-bogus.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-bogus.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-bogus.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - bogus methods - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-insensitive.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-insensitive.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-insensitive.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-insensitive.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - case-insensitive methods test - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-sensitive.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-sensitive.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-sensitive.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-case-sensitive.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - case-sensitive methods test - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-insecure.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-insecure.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-insecure.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-insecure.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - "insecure" methods - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-responsetype-set-sync.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-responsetype-set-sync.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-responsetype-set-sync.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-method-responsetype-set-sync.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() sync request not allowed if responseType is set - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-send.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-send.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-send.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-send.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - open() - send() - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-sync-send.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-sync-send.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-sync-send.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-open-sync-send.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - open() (sync) - send() - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-referer.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-referer.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-referer.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-referer.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - value of Referer header - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-send-open.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-send-open.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-send-open.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-send-open.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - send() - open() - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-sync-open-send.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-sync-open-send.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-sync-open-send.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-sync-open-send.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,12 +4,12 @@ XMLHttpRequest: open() (sync) - send() - open() - - - - - - + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-about-blank-window.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-about-blank-window.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-about-blank-window.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-about-blank-window.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,9 +4,9 @@ XMLHttpRequest: open() resolving URLs (about:blank iframe) - - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted-after-open.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted-after-open.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted-after-open.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted-after-open.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: open() resolving URLs - insert <base> after open() - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-base-inserted.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: open() resolving URLs - insert <base> - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-bogus.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-bogus.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-bogus.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-bogus.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - bogus URLs - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-encoding.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-encoding.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-encoding.htm 2014-11-14 09:37:17.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-encoding.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ XMLHttpRequest: open() - URL encoding - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-fragment.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-fragment.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-fragment.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-fragment.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() resolving URLs - fragment identifier - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window-2.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window-2.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window-2.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window-2.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - resolving URLs (javascript: <iframe>; 2) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-javascript-window.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - resolving URLs (javascript: <iframe>; 1) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-2.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-2.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-2.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-2.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() resolving URLs (multi-Window; 2; evil) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-5.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-5.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-5.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window-5.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() resolving URLs (multi-Window; 5) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-multi-window.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() resolving URLs (multi-Window; 1) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-origin.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-origin.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-origin.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-origin.htm 2014-11-26 21:45:53.000000000 +0000 @@ -6,7 +6,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-simple.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-simple.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-simple.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-url-worker-simple.htm 2014-11-26 21:45:53.000000000 +0000 @@ -6,7 +6,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-user-password-non-same-origin.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-user-password-non-same-origin.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/open-user-password-non-same-origin.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/open-user-password-non-same-origin.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: open() - user/pass argument and non same-origin URL doesn't throw - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-done-state.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-done-state.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-done-state.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-done-state.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-loading-state.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-loading-state.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-loading-state.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-loading-state.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/progress-events-response-data-gzip.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/progress-events-response-data-gzip.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/progress-events-response-data-gzip.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/progress-events-response-data-gzip.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth1/auth.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth1/auth.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth1/auth.py 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth1/auth.py 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,10 @@ import imp import os +here = os.path.split(os.path.abspath(__file__))[0] + def main(request, response): - auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), - "XMLHttpRequest", - "resources", + auth = imp.load_source("", os.path.join(here, + "..", "authentication.py")) return auth.main(request, response) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth2/auth.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth2/auth.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth2/auth.py 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth2/auth.py 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,10 @@ import imp import os +here = os.path.split(os.path.abspath(__file__))[0] + def main(request, response): - auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), - "XMLHttpRequest", - "resources", + auth = imp.load_source("", os.path.join(here, + "..", "authentication.py")) return auth.main(request, response) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth3/auth.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth3/auth.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth3/auth.py 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth3/auth.py 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,10 @@ import imp import os +here = os.path.split(os.path.abspath(__file__))[0] + def main(request, response): - auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), - "XMLHttpRequest", - "resources", + auth = imp.load_source("", os.path.join(here, + "..", "authentication.py")) return auth.main(request, response) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth4/auth.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth4/auth.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth4/auth.py 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/auth4/auth.py 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,10 @@ import imp import os +here = os.path.split(os.path.abspath(__file__))[0] + def main(request, response): - auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), - "XMLHttpRequest", - "resources", + auth = imp.load_source("", os.path.join(here, + "..", "authentication.py")) return auth.main(request, response) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/chunked.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/chunked.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/chunked.py 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/chunked.py 2014-11-26 21:45:53.000000000 +0000 @@ -7,7 +7,7 @@ response.headers.set("Transfer-Encoding", "chunked"); response.headers.set("Trailer", "X-Test-Me"); response.headers.set("Content-Type", "text/plain"); - response.writer.flush() + response.write_status_headers() for value in chunks: response.writer.write("%d\r\n" % len(value)) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js 2014-11-26 21:45:53.000000000 +0000 @@ -1,5 +1,5 @@ /* Test adapted from Alex Vincent's XHR2 timeout tests, written for Mozilla. - https://hg.mozilla.org/mozilla-central/file/tip/dom/base/test/ + https://hg.mozilla.org/mozilla-central/file/tip/content/base/test/ Released into the public domain or under BSD, according to https://bugzilla.mozilla.org/show_bug.cgi?id=525816#c86 */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-arraybuffer.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-arraybuffer.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-arraybuffer.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-arraybuffer.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,8 +1,8 @@ - - + + XMLHttpRequest: The response attribute: ArrayBuffer data diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-blob.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-blob.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-blob.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-blob.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,9 @@ - - - + + + XMLHttpRequest: The response attribute: Blob data diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-progress.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-progress.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-progress.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-data-progress.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,10 +5,10 @@ XMLHttpRequest: progress events grow response body size - - - - + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-invalid-responsetype.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-invalid-responsetype.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-invalid-responsetype.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-invalid-responsetype.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: response is plain text if responseType is set to an invalid string - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-json.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-json.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/response-json.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/response-json.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,9 +5,9 @@ - - - + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetext-decoding.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetext-decoding.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetext-decoding.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetext-decoding.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: responseText decoding - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetype.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetype.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetype.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsetype.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,7 +3,7 @@ XMLHttpRequest.responseType - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-basic.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-basic.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-basic.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-basic.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: responseXML basic test - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: responseXML document properties - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-media-type.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-media-type.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-media-type.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-media-type.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: responseXML MIME type tests - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-document-types.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-document-types.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-document-types.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-document-types.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,9 +4,9 @@ XMLHttpRequest: responseXML/responseText on other responseType - - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-well-formed.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-well-formed.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-well-formed.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/responsexml-non-well-formed.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: responseXML non well-formed tests - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - Accept - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept-language.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept-language.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept-language.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-accept-language.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - Accept-Language - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-after-setting-document-domain.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-after-setting-document-domain.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-after-setting-document-domain.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-after-setting-document-domain.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: send() - "Basic" authenticated CORS requests with user name and password passed to open() (asserts failure) - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm 2014-11-26 21:45:53.000000000 +0000 @@ -6,8 +6,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm 2014-11-26 21:45:53.000000000 +0000 @@ -6,8 +6,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
- - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-existing-session-manual.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-existing-session-manual.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-existing-session-manual.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-existing-session-manual.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +

Please follow these steps to complete the test:

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: WWW-Authenticate challenge when user,pass are not passed to open() - +

Please follow these steps to complete the test:

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-manual.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-manual.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-manual.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-authentication-prompt-manual.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - "Basic" authentication gets 401 response - +

Please follow these steps to complete the test:

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-conditional.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-conditional.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-conditional.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-conditional.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - conditional requests - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-charset.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-charset.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-charset.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-charset.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: send() - charset parameter of Content-Type - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-string.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-string.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-string.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-content-type-string.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - Content-Type - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-arraybuffer.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-arraybuffer.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-arraybuffer.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-arraybuffer.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,9 @@ - - - + + + XMLHttpRequest: The send() method: ArrayBuffer data diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-blob.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-blob.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-blob.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-blob.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,10 +1,10 @@ - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-es-object.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-es-object.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-es-object.htm 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-es-object.htm 2014-11-26 21:45:53.000000000 +0000 @@ -0,0 +1,61 @@ + + +XMLHttpRequest: passing objects to send() + + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-formdata.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-formdata.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-formdata.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-formdata.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,9 @@ - - - + + + XmlHttpRequest: The send() method: FormData data diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-unexpected-tostring.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-unexpected-tostring.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-unexpected-tostring.htm 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-data-unexpected-tostring.htm 2014-11-26 21:45:53.000000000 +0000 @@ -0,0 +1,57 @@ + + +XMLHttpRequest: passing objects that interfere with the XHR instance to send() + + + + + + +
+ + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-basic.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-basic.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-basic.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-basic.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: send() - data argument - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document-bogus.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document-bogus.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document-bogus.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document-bogus.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - unserializable Document - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-document.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-empty.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-empty.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-empty.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-empty.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: send("") - empty entity body - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head-async.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head-async.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head-async.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head-async.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - non-empty data argument and GET/HEAD - async, no upload events should fire - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-get-head.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - non-empty data argument and GET/HEAD - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-none.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-none.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-none.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-entity-body-none.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send(null) - no entity body - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-async-events.sub.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-async-events.sub.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-async-events.sub.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-async-events.sub.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,11 +1,11 @@ - - - - - + + + + + XmlHttpRequest: The send() method: Fire a progress event named error when Network error happens (synchronous flag is unset) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-sync-events.sub.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-sync-events.sub.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-sync-events.sub.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-network-error-sync-events.sub.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,9 +1,9 @@  - - - + + + XmlHttpRequest: The send() method: Throw a "throw an "NetworkError" exception when Network error happens (synchronous flag is set) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-non-same-origin.sub.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-non-same-origin.sub.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-non-same-origin.sub.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-non-same-origin.sub.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,8 +5,8 @@ - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadend.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadend.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadend.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadend.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,9 +4,9 @@ XMLHttpRequest: The send() method: Fire a progress event named loadend (no response entity body) - - - + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadstart.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadstart.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadstart.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-loadstart.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,10 +1,10 @@ - - - - + + + + XMLHttpRequest: The send() method: Fire a progress event named loadstart (no response entity body and the state is LOADING) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-order.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-order.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-order.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-no-response-event-order.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,14 +1,14 @@ - - - - - - - - + + + + + + + + XMLHttpRequest: The send() method: event order when there is no response entity body @@ -26,7 +26,7 @@ var expect = ["loadstart", 4, "load", "loadend"]; var actual = []; - xhr.onreadystatechange = function() + xhr.onreadystatechange = test.step_func(function() { test.step(function() { @@ -39,24 +39,19 @@ actual.push(xhr.readyState); } }); - }; + }); - xhr.onloadstart = function(e){ actual.push(e.type); }; - xhr.onload = function(e){ actual.push(e.type); }; - xhr.onloadend = function(e){ actual.push(e.type); VerifyResult()}; - - xhr.upload.onloadstart = function(e){ assert_unreached('upload.'+e.type); }; - xhr.upload.onload = function(e){ assert_unreached('upload.'+e.type); }; - xhr.upload.onloadend = function(e){ assert_unreached('upload.'+e.type); }; - - function VerifyResult() - { - test.step(function() - { - assert_array_equals(actual, expect); - test.done(); - }); - }; + xhr.onloadstart = test.step_func(function(e){ actual.push(e.type); }); + xhr.onload = test.step_func(function(e){ actual.push(e.type); }); + xhr.onloadend = test.step_func(function(e){ + actual.push(e.type); + assert_array_equals(actual, expect); + test.done(); + }); + + xhr.upload.onloadstart = test.step_func(function(e){ assert_unreached('upload.'+e.type); }); + xhr.upload.onload = test.step_func(function(e){ assert_unreached('upload.'+e.type); }); + xhr.upload.onloadend = test.step_func(function(e){ assert_unreached('upload.'+e.type); }); xhr.open("POST", "./resources/content.py", true); xhr.send(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus-sync.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus-sync.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus-sync.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-bogus-sync.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - Redirects (bogus Location header; sync) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - Redirects (basics) - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,11 +4,11 @@ XMLHttpRequest: send() - Redirects (infinite loop) - - - - - + + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite-sync.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite-sync.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite-sync.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-infinite-sync.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,9 +4,9 @@ XMLHttpRequest: send() - Redirects (infinite loop; sync) - - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-no-location.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-no-location.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-no-location.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-redirect-no-location.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: send() - Redirects (no Location header) - + - + XMLHttpRequest: sync requests should block events on pending async requests diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,11 +1,11 @@ - - - - - + + + + + XMLHttpRequest: The send() method: Fire an event named loadend (no response entity body and the synchronous flag is set) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-load.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-load.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-load.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-load.htm 2014-11-26 21:45:53.000000000 +0000 @@ -1,11 +1,11 @@ - - - - - + + + + + XMLHttpRequest: The send() method: Fire an event named load (no response entity body and the synchronous flag is set) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-order.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-order.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-order.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-no-response-event-order.htm 2014-11-26 21:45:53.000000000 +0000 @@ -2,15 +2,15 @@ XMLHttpRequest: The send() method: event order when synchronous flag is set and there is no response entity body - - - - - - - - - + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-response-event-order.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-response-event-order.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-response-event-order.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-response-event-order.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,15 +4,15 @@ XMLHttpRequest: The send() method: event order when synchronous flag is set - - - - - - - - - + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-timeout.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-timeout.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-timeout.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-sync-timeout.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: timeout during sync send() should not run - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-timeout-events.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-timeout-events.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/send-timeout-events.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/send-timeout-events.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,10 +4,10 @@ XMLHttpRequest: The send() method: timeout is not 0 - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-after-send.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-after-send.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-after-send.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-after-send.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setRequestHeader() after send() - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setRequestHeader() - empty header - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-before-open.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-before-open.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-before-open.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-before-open.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setRequestHeader() before open() - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-name.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-name.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-name.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-name.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,37 +5,44 @@ - +
+ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-value.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-value.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-value.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-bogus-value.htm 2014-11-26 21:45:53.000000000 +0000 @@ -5,7 +5,7 @@ XMLHttpRequest: setRequestHeader() value argument checks - +
@@ -14,19 +14,18 @@ test(function() { var client = new XMLHttpRequest() client.open("GET", "...") - // Older versions of the XHR spec use SyntaxError here, however, - // TypeError is the right error for this test per https://www.w3.org/Bugs/Public/show_bug.cgi?id=23346 - assert_throws(new TypeError(), function() { client.setRequestHeader("x-test", value) }, ' given value ' + value+', ') + assert_throws("SyntaxError", function() { client.setRequestHeader("x-test", value) }, ' given value ' + value+', ') }) } try_value("t\rt") try_value("t\nt") try_value("ďľď˝˝ďľ„") + test(function() { var client = new XMLHttpRequest() client.open("GET", "...") assert_throws(new TypeError(), function() { client.setRequestHeader("x-test") }) - }) + }, 'Omitted value argument') diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-case-insensitive.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-case-insensitive.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-case-insensitive.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-case-insensitive.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setRequestHeader() - headers that differ in case - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-allowed.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-allowed.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-allowed.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-allowed.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setRequestHeader() - headers that are allowed - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-forbidden.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-forbidden.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-forbidden.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-header-forbidden.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setRequestHeader() - headers that are forbidden - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-invalid-arguments.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-invalid-arguments.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-invalid-arguments.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-invalid-arguments.htm 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - XMLHttpRequest: setRequestHeader() with invalid arguments - - - - -
- - - - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm 2014-11-26 21:45:53.000000000 +0000 @@ -6,8 +6,8 @@ XMLHttpRequest: setRequestHeader() and open() - - + +

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/status-async.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/status-async.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/status-async.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/status-async.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,10 +4,10 @@ XMLHttpRequest: status/statusText - various responses - - - - + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/status-basic.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/status-basic.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/status-basic.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/status-basic.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,10 +4,10 @@ XMLHttpRequest: status/statusText - various responses - - - - + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/status-error.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/status-error.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/status-error.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/status-error.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: status error handling - - + +

This shouldn't be tested inside a tunnel.

diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-cors-async.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-cors-async.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-cors-async.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-cors-async.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,11 +4,11 @@ XMLHttpRequest: timeout event and cross-origin request - - - - - + + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-sync.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-sync.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-sync.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/timeout-sync.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,8 +4,8 @@ XMLHttpRequest: timeout not allowed for sync requests - - + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-set.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-set.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-set.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-set.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setting withCredentials and reading value back - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-wrong-state.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-wrong-state.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-wrong-state.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/withcredentials-wrong-state.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: setting withCredentials when not in UNSENT, OPENED state - +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-basic.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-basic.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-basic.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-basic.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,9 +4,9 @@ XMLHttpRequest: prototype and members - - - + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,7 +4,7 @@ XMLHttpRequest: implements EventTarget - + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,13 +4,13 @@ XMLHttpRequest: members during network errors - - - - - - - + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,15 +4,15 @@ XMLHttpRequest: members during network errors (sync) - - - - - - - - - + + + + + + + + +
diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,14 +3,14 @@ XHR2 Timeout Property Tests - - - - - - - - + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,10 +3,10 @@ XHR2 Timeout Property Tests - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,11 +3,11 @@ XHR2 Timeout Property Tests - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,10 +3,10 @@ XHR2 Timeout Property Tests - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,11 +3,11 @@ XHR2 Timeout Property Tests - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,8 +3,8 @@ XHR2 Timeout Property Tests - - + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,13 +3,13 @@ XHR2 Timeout Property Tests - + - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,14 +3,14 @@ XHR2 Timeout Property Tests in Worker - - - - - - - - + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,11 +3,11 @@ XHR2 Timeout Property Tests in Worker - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,10 +3,10 @@ XHR2 Timeout Property Tests in Worker - - - - + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,11 +3,11 @@ XHR2 Timeout Property Tests in Worker - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,11 +3,11 @@ XHR2 Timeout Property Tests in Worker - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html 2014-11-26 21:45:53.000000000 +0000 @@ -3,11 +3,11 @@ XHR2 Timeout Property Tests in Worker - - - - - + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-unsent.htm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-unsent.htm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-unsent.htm 2014-11-14 09:37:18.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/tests/XMLHttpRequest/xmlhttprequest-unsent.htm 2014-11-26 21:45:53.000000000 +0000 @@ -4,15 +4,15 @@ XMLHttpRequest: members during UNSENT - - - - - - - - - + + + + + + + + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/wptrunner.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/wptrunner.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/web-platform/wptrunner.ini 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/web-platform/wptrunner.ini 2014-11-26 21:46:00.000000000 +0000 @@ -7,5 +7,20 @@ sync_path = sync [paths] +prefs = ../profiles +run_info = . + +[manifest:upstream] tests = tests metadata = meta +url_base = / + +[manifest:outbound] +tests = outbound/tests +metadata = outbound/meta +url_base = /_outbound/ + +[manifest:mozilla] +tests = mozilla/tests +metadata = mozilla/meta +url_base = /_mozilla/ \ No newline at end of file diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/client.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/client.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/client.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/client.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,231 @@ +var spdy = require('../spdy'); +var assert = require('assert'); +var util = require('util'); +var net = require('net'); +var https = require('https'); +var EventEmitter = require('events').EventEmitter; + +var proto = {}; + +function instantiate(base) { + function Agent(options) { + base.call(this, options); + + if (!this.options.spdy) + this.options.spdy = {}; + + this._init(); + + // Hack for node.js v0.10 + this.createConnection = proto.createConnection; + + // No chunked encoding + this.keepAlive = false; + }; + util.inherits(Agent, base); + + // Copy prototype methods + Object.keys(proto).forEach(function(key) { + this[key] = proto[key]; + }, Agent.prototype); + + return Agent; +}; + +proto._init = function init() { + var self = this; + + var state = {}; + // Find super's `createConnection` method + var createConnection; + var cons = this.constructor.super_; + do { + createConnection = cons.prototype.createConnection; + + if (cons.super_ === EventEmitter || !cons.super_) + break; + cons = cons.super_; + } while (!createConnection); + + if (!createConnection) + createConnection = this.createConnection || net.createConnection; + + // TODO(indutny): Think about falling back to http/https + var socket = createConnection.call(this, util._extend({ + NPNProtocols: ['spdy/3.1', 'spdy/3', 'spdy/2'], + ALPNProtocols: ['spdy/3.1', 'spdy/3', 'spdy/2'] + }, this.options)); + state.socket = socket; + + // Header compression is disabled by default in clients to prevent CRIME + // attacks. Don't enable it unless you know what you're doing. + if (this.options.spdy.headerCompression !== true) + this.options.spdy.headerCompression = false; + + // Create SPDY connection using newly created socket + var connection = new spdy.Connection(socket, + util._extend(this.options.spdy, { + isServer: false + })); + state.connection = connection; + + connection.on('error', function(err) { + self.emit('error', err); + }); + + // Select SPDY version + if (this.options.spdy.ssl !== false && !this.options.spdy.version) { + // SSL, wait for NPN or ALPN to happen + socket.once('secureConnect', function() { + var selectedProtocol = socket.npnProtocol || socket.alpnProtocol; + if (selectedProtocol === 'spdy/2') + connection._setVersion(2); + else if (selectedProtocol === 'spdy/3') + connection._setVersion(3); + else if (selectedProtocol === 'spdy/3.1') + connection._setVersion(3.1); + else + socket.emit('error', new Error('No supported SPDY version')); + }); + } else { + // No SSL, use fixed version + connection._setVersion(this.options.spdy.version || 3); + } + + // Destroy PUSH streams until the listener will be added + connection.on('stream', function(stream) { + stream.on('error', function() {}); + stream.destroy(); + }); + state.pushServer = null; + + this.on('newListener', this._onNewListener.bind(this)); + this.on('removeListener', this._onRemoveListener.bind(this)); + + // Client has odd-numbered stream ids + state.id = 1; + this._spdyState = state; +}; + +// +// ### function onNewListener (type, listener) +// #### @type {String} Event type +// #### @listener {Function} Listener callback +// +proto._onNewListener = function onNewListener(type, listener) { + if (type !== 'push') + return; + + var state = this._spdyState; + if (state.pushServer) + return state.pushServer.on('translated-request', listener); + + state.pushServer = require('http').createServer(listener); + state.connection.removeAllListeners('stream'); + state.connection.on('stream', function(stream) { + state.pushServer.emit('connection', stream); + }); + + state.pushServer.on('request', function(req) { + // Populate trailing headers + req.connection.on('headers', function(headers) { + Object.keys(headers).forEach(function(key) { + req.trailers[key] = headers[key]; + }); + req.emit('trailers', headers); + }); + + this.emit('translated-request', req); + }); +}; + +// +// ### function onRemoveListener (type, listener) +// #### @type {String} Event type +// #### @listener {Function} Listener callback +// +proto._onRemoveListener = function onRemoveListener(type, listener) { + if (type !== 'push') + return; + + var state = this._spdyState; + if (!state.pushServer) + return; + + state.pushServer.removeListener('translated-request', listener); +}; + +// +// ### function createConnection (options) +// +proto.createConnection = function createConnection(options) { + if (!options) + options = {}; + + var state = this._spdyState; + var stream = new spdy.Stream(state.connection, { + id: state.id, + priority: options.priority || 7, + client: true, + decompress: options.spdy.decompress == undefined ? true : + options.spdy.decompress + }); + state.id += 2; + state.connection._addStream(stream); + + return stream; +}; + +// +// ### function close (callback) +// #### @callback {Function} +// Close underlying socket and terminate all streams +// +proto.close = function close(callback) { + this._spdyState.socket.destroySoon(); + if (callback) + this._spdyState.socket.once('close', callback); +}; + +// +// ### function ping (callback) +// #### @callback {Function} +// Send PING frame and invoke callback once received it back +// +proto.ping = function ping(callback) { + return this._spdyState.connection.ping(callback); +}; + +// +// Default Agent +// +exports.Agent = instantiate(https.Agent); + +// +// ### function create (base, options) +// #### @base {Function} (optional) base server class (https.Server) +// #### @options {Object} tls server options +// @constructor wrapper +// +exports.create = function create(base, options) { + var agent; + if (typeof base === 'function') { + agent = instantiate(base); + } else { + agent = exports.Agent; + + options = base; + base = null; + } + + // Instantiate http server if `ssl: false` + if (!base && + options && + options.spdy && + options.spdy.plain && + options.spdy.ssl === false) { + return exports.create(require('http').Agent, options); + } + + return new agent(options); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/connection.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/connection.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/connection.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/connection.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,644 @@ +var util = require('util'); +var assert = require('assert'); +var spdy = require('../spdy'); +var constants = spdy.protocol.constants; + +var Stream = spdy.Stream; + +// +// ### function Connection (socket, state, server) +// #### @socket {net.Socket} server's connection +// #### @options {Object} Connection options +// #### @server {net.Server} server +// Abstract connection @constructor +// +function Connection(socket, options, server) { + process.EventEmitter.call(this); + + var state = {}; + this._spdyState = state; + + // NOTE: There's a big trick here. Connection is used as a `this` argument + // to the wrapped `connection` event listener. + // socket end doesn't necessarly mean connection drop + this.httpAllowHalfOpen = true; + + // Socket timeout + this.timeout = server && server.timeout || 0; + + // Defaults + state.maxStreams = options.maxStreams || Infinity; + state.initialSinkSize = constants.DEFAULT_WINDOW; + state.initialWindowSize = options.windowSize || 1 << 20; + state.autoSpdy31 = options.autoSpdy31; + + // Connection-level flow control + state.sinkSize = state.initialSinkSize; + state.windowSize = constants.DEFAULT_WINDOW; + + // Interleaving configuration + state.maxChunk = options.maxChunk === undefined ? 8 * 1024 : options.maxChunk; + + // Various state info + state.closed = false; + state.pool = spdy.zlibpool.create(options.headerCompression); + state.counters = { + pushCount: 0, + streamCount: 0 + }; + state.socketBuffering = false; + + state.version = null; + state.deflate = null; + state.inflate = null; + + // Init streams list + state.isServer = options.isServer; + state.streams = {}; + state.streamCount = 0; + state.lastId = 0; + state.pushId = 0; + state.pingId = state.isServer ? 0 : 1; + state.pings = {}; + state.goaway = false; + + // X-Forwarded feature + state.xForward = null; + + // Initialize scheduler + state.scheduler = spdy.scheduler.create(this); + + // Create parser and hole for framer + state.parser = spdy.protocol.parser.create(this); + state.framer = spdy.protocol.framer.create(); + + // Lock data + state.locked = false; + state.lockQueue = []; + + this.socket = socket; + this.encrypted = socket.encrypted; + this.readable = true; + this.writable = true; + + this._init(); +} +util.inherits(Connection, process.EventEmitter); +exports.Connection = Connection; + +Connection.prototype._init = function init() { + var self = this; + var state = this._spdyState; + var pool = state.pool; + var pair = null; + var sentSettings = false; + + // Initialize parser + this._spdyState.parser.on('frame', this._handleFrame.bind(this)); + + this._spdyState.parser.on('version', function onversion(version) { + var prev = state.version; + var framer = state.framer; + + state.version = version; + + // Ignore transition to 3.1 + if (!prev) { + pair = pool.get('spdy/' + version); + state.deflate = pair.deflate; + state.inflate = pair.inflate; + framer.setCompression(pair.deflate, pair.inflate); + } + framer.setVersion(version); + + // Send settings frame (once) + if (!sentSettings) { + sentSettings = true; + framer.settingsFrame({ + maxStreams: state.maxStreams, + windowSize: state.initialWindowSize + }, function(err, frame) { + if (err) + return self.emit('error', err); + self.write(frame); + }); + + // Send WINDOW_UPDATE for 3.1 + self._sendWindowUpdate(true); + } + }); + + // Propagate parser errors + state.parser.on('error', function onParserError(err) { + self.emit('error', err); + }); + + this.socket.pipe(state.parser); + + // 2 minutes socket timeout + this.socket.setTimeout(this.timeout); + this.socket.once('timeout', function ontimeout() { + self.socket.destroy(); + }); + + // Allow high-level api to catch socket errors + this.socket.on('error', function onSocketError(e) { + self.emit('error', e); + }); + + this.socket.once('close', function onclose() { + var err = new Error('socket hang up'); + err.code = 'ECONNRESET'; + self._destroyStreams(err); + self.emit('close'); + + state.closed = true; + if (pair) + pool.put(pair); + }); + + // Do not allow half-open connections + this.socket.allowHalfOpen = false; + + if (spdy.utils.isLegacy) { + this.socket.on('drain', function ondrain() { + self.emit('drain'); + }); + } + + // for both legacy and non-legacy, when our socket is ready for writes again, + // drain the sinks in case they were queuing due to socketBuffering. + this.socket.on('drain', function () { + state.socketBuffering = false; + Object.keys(state.streams).forEach(function(id) { + state.streams[id]._drainSink(0); + }); + }); +}; + +// +// ### function handleFrame (frame) +// #### @frame {Object} SPDY frame +// +Connection.prototype._handleFrame = function handleFrame(frame) { + var state = this._spdyState; + + if (state.closed) + return; + + var stream; + + // Create new stream + if (frame.type === 'SYN_STREAM') { + stream = this._handleSynStream(frame); + } else { + if (frame.id !== undefined) { + // Load created one + stream = state.streams[frame.id]; + + // Fail if not found + if (stream === undefined && + !(frame.type === 'WINDOW_UPDATE' && frame.id === 0)) { + if (frame.type === 'RST_STREAM') + return; + this._rst(frame.id, constants.rst.INVALID_STREAM); + return; + } + } + + // Emit 'data' event + if (frame.type === 'DATA') { + this._handleData(stream, frame); + // Reply for client stream + } else if (frame.type === 'SYN_REPLY') { + // If stream not client - send RST + if (!stream._spdyState.isClient) { + this._rst(frame.id, constants.rst.PROTOCOL_ERROR); + return; + } + + stream._handleResponse(frame); + + // Destroy stream if we were asked to do this + } else if (frame.type === 'RST_STREAM') { + stream._spdyState.rstCode = 0; + stream._spdyState.closedBy.us = true; + stream._spdyState.closedBy.them = true; + + // Emit error on destroy + var err = new Error('Received rst: ' + frame.status); + err.code = 'RST_STREAM'; + err.status = frame.status; + stream.destroy(err); + // Respond with same PING + } else if (frame.type === 'PING') { + this._handlePing(frame.pingId); + } else if (frame.type === 'SETTINGS') { + this._setDefaultWindow(frame.settings); + } else if (frame.type === 'GOAWAY') { + state.goaway = frame.lastId; + this.writable = false; + } else if (frame.type === 'WINDOW_UPDATE') { + if (stream) + stream._drainSink(frame.delta); + else + this._drainSink(frame.delta); + } else if (frame.type === 'HEADERS') { + stream.emit('headers', frame.headers); + } else if (frame.type === 'X_FORWARDED') { + state.xForward = frame.host; + } else { + console.error('Unknown type: ', frame.type); + } + } + + // Handle half-closed + if (frame.fin) { + // Don't allow to close stream twice + if (stream._spdyState.closedBy.them) { + stream._spdyState.rstCode = constants.rst.PROTOCOL_ERROR; + stream.emit('error', 'Already half-closed'); + } else { + stream._spdyState.closedBy.them = true; + + // Receive FIN + stream._recvEnd(); + + stream._handleClose(); + } + } +}; + +// +// ### function handleSynStream (frame) +// #### @frame {Object} SPDY frame +// +Connection.prototype._handleSynStream = function handleSynStream(frame) { + var state = this._spdyState; + var associated; + + if (state.goaway && state.goaway < frame.id) + return this._rst(frame.id, constants.rst.REFUSED_STREAM); + + // PUSH stream + if (!state.isServer) { + // Incorrect frame id + if (frame.id % 2 === 1 || frame.associated % 2 === 0) + return this._rst(frame.id, constants.rst.PROTOCOL_ERROR); + + associated = state.streams[frame.associated]; + + // Fail if not found + if (associated === undefined) { + if (frame.type === 'RST_STREAM') + return; + this._rst(frame.id, constants.rst.INVALID_STREAM); + return; + } + } + + var stream = new Stream(this, frame); + this._addStream(stream); + + // Associate streams + if (associated) { + stream.associated = associated; + } + + // TODO(indutny) handle stream limit + this.emit('stream', stream); + stream._start(frame.url, frame.headers); + + return stream; +}; + +// +// ### function _handleData (stream, frame) +// #### @stream {Stream} SPDY Stream +// #### @frame {Object} SPDY frame +// +Connection.prototype._handleData = function handleData(stream, frame) { + var state = this._spdyState; + + if (frame.data.length > 0) { + if (stream._spdyState.closedBy.them) { + stream._spdyState.rstCode = constants.rst.PROTOCOL_ERROR; + stream.emit('error', 'Writing to half-closed stream'); + } else { + // Connection-level flow control + state.windowSize -= frame.data.length; + this._sendWindowUpdate(); + stream._recv(frame.data); + } + } +}; + +// +// ### function sendWindowUpdate (force) +// #### @force {Boolean} send even if windowSize is positive +// Send WINDOW_UPDATE if needed +// +Connection.prototype._sendWindowUpdate = function sendWindowUpdate(force) { + var state = this._spdyState; + + if (state.version < 3.1 && (!state.isServer || !state.autoSpdy31) || + state.windowSize > state.initialWindowSize / 2 && !force) { + return; + } + + var self = this; + var delta = state.initialWindowSize - state.windowSize; + if (delta === 0) + return; + + state.windowSize += delta; + state.framer.windowUpdateFrame(0, delta, function(err, frame) { + if (err) + return self.emit('error', err); + self.write(frame); + }); +}; + +// +// ### function _drainSink (delta) +// #### @delta {Number} WINDOW_UPDATE delta value +// +Connection.prototype._drainSink = function drainSink(delta) { + var state = this._spdyState; + + // Switch to 3.1 + if (state.version !== 3.1) { + this._setVersion(3.1); + this._sendWindowUpdate(); + } + + state.sinkSize += delta; + + if (state.sinkSize <= 0) + return; + + this.emit('drain'); + + // Try to write all pending data to the socket + Object.keys(state.streams).forEach(function(id) { + state.streams[id]._drainSink(0); + }); +}; + +// +// ### function setVersion (version) +// #### @version {Number} Protocol version +// Set protocol version to use +// +Connection.prototype._setVersion = function setVersion(version) { + this._spdyState.parser.setVersion(version); +}; + +// +// ### function addStream (stream) +// #### @stream {Stream} +// +Connection.prototype._addStream = function addStream(stream) { + var state = this._spdyState; + var id = stream._spdyState.id; + if (state.streams[id]) + return; + state.streams[id] = stream; + + // Update lastId + state.lastId = Math.max(state.lastId, id); + + var isClient = id % 2 == 1; + if (isClient && state.isServer || !isClient && !state.isServer) + state.streamCount++; +}; + +// +// ### function removeStream (stream) +// #### @stream {Stream} +// +Connection.prototype._removeStream = function removeStream(stream) { + var state = this._spdyState; + var id = stream._spdyState.id; + if (!state.streams[id]) + return; + + delete state.streams[id]; + + var isClient = id % 2 == 1; + if (isClient && state.isServer || !isClient && !state.isServer) + state.streamCount--; + + if (!state.isServer && + state.goaway && + state.streamCount === 0 && + this.socket) { + this.socket.destroySoon(); + } +}; + +// +// ### function destroyStreams (err) +// #### @err {Error} *optional* +// Destroys all active streams +// +Connection.prototype._destroyStreams = function destroyStreams(err) { + var state = this._spdyState; + var streams = state.streams; + state.streams = {}; + state.streamCount = 0; + Object.keys(streams).forEach(function(id) { + streams[id].destroy(); + }); +}; + +// +// ### function _rst (streamId, code, extra) +// #### @streamId {Number} +// #### @code {Number} +// #### @extra {String} +// Send RST frame +// +Connection.prototype._rst = function rst(streamId, code, extra) { + var self = this; + this._spdyState.framer.rstFrame(streamId, code, extra, function(err, frame) { + if (err) + return self.emit('error', err); + self.write(frame); + }); +}; + +// +// ### function lock (callback) +// #### @callback {Function} continuation callback +// Acquire lock +// +Connection.prototype._lock = function lock(callback) { + if (!callback) + return; + + var state = this._spdyState; + if (state.locked) { + state.lockQueue.push(callback); + } else { + state.locked = true; + callback(null); + } +}; + +// +// ### function unlock () +// Release lock and call all buffered callbacks +// +Connection.prototype._unlock = function unlock() { + var state = this._spdyState; + if (state.locked) { + if (state.lockQueue.length) { + var cb = state.lockQueue.shift(); + cb(null); + } else { + state.locked = false; + } + } +}; + +// +// ### function write (data, encoding) +// #### @data {String|Buffer} data +// #### @encoding {String} (optional) encoding +// Writes data to socket +// +Connection.prototype.write = function write(data, encoding) { + if (this.socket.writable) { + var wroteThrough = this.socket.write(data, encoding); + // if write returns false, the socket layer is buffering the data, so let's + // set a flag that we can use to create some backpressure + if (!wroteThrough) + this._spdyState.socketBuffering = true; + return wroteThrough; + } +}; + +// +// ### function _setDefaultWindow (settings) +// #### @settings {Object} +// Update the default transfer window -- in the connection and in the +// active streams +// +Connection.prototype._setDefaultWindow = function _setDefaultWindow(settings) { + if (!settings) + return; + if (!settings.initial_window_size || + settings.initial_window_size.persisted) { + return; + } + var state = this._spdyState; + state.initialSinkSize = settings.initial_window_size.value; + + Object.keys(state.streams).forEach(function(id) { + state.streams[id]._updateSinkSize(settings.initial_window_size.value); + }); +}; + +// +// ### function handlePing (id) +// #### @id {Number} PING id +// +Connection.prototype._handlePing = function handlePing(id) { + var self = this; + var state = this._spdyState; + + var ours = state.isServer && (id % 2 === 0) || + !state.isServer && (id % 2 === 1); + + // Handle incoming PING + if (!ours) { + state.framer.pingFrame(id, function(err, frame) { + if (err) + return self.emit('error', err); + self.write(frame); + }); + return; + } + + // Handle reply PING + if (!state.pings[id]) + return; + var ping = state.pings[id]; + delete state.pings[id]; + + if (ping.cb) + ping.cb(null); +}; + +// +// ### function ping (callback) +// #### @callback {Function} +// Send PING frame and invoke callback once received it back +// +Connection.prototype.ping = function ping(callback) { + var self = this; + var state = this._spdyState; + var id = state.pingId; + + state.pingId += 2; + + state.framer.pingFrame(id, function(err, frame) { + if (err) + return self.emit('error', err); + + state.pings[id] = { cb: callback }; + self.write(frame); + }); +}; + +// +// ### function getCounter (name) +// #### @name {String} Counter name +// Get counter value +// +Connection.prototype.getCounter = function getCounter(name) { + return this._spdyState.counters[name]; +}; + +// +// ### function cork () +// Accumulate data before writing out +// +Connection.prototype.cork = function cork() { + if (this.socket && this.socket.cork) + this.socket.cork(); +}; + +// +// ### function uncork () +// Write out accumulated data +// +Connection.prototype.uncork = function uncork() { + if (this.socket && this.socket.uncork) + this.socket.uncork(); +}; + +Connection.prototype.end = function end() { + var self = this; + var state = this._spdyState; + + state.framer.goawayFrame(state.lastId, + constants.goaway.OK, + function(err, frame) { + if (err) + return self.emit('error', err); + + self.write(frame, function() { + state.goaway = state.lastId; + + // Destroy socket if there are no streams + if (!state.isServer && + state.goaway && + state.streamCount === 0 && + self.socket) { + self.socket.destroySoon(); + } + }); + }); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/parser.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/parser.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/parser.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/parser.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,235 +0,0 @@ -var parser = exports; - -var spdy = require('../spdy'), - util = require('util'), - stream = require('stream'), - Buffer = require('buffer').Buffer; - -var legacy = !stream.Duplex; - -if (legacy) { - var DuplexStream = stream; -} else { - var DuplexStream = stream.Duplex; -} - -// -// ### function Parser (connection) -// #### @connection {spdy.Connection} connection -// SPDY protocol frames parser's @constructor -// -function Parser(connection) { - DuplexStream.call(this); - - this.drained = true; - this.paused = false; - this.buffer = []; - this.buffered = 0; - this.waiting = 8; - - this.state = { type: 'frame-head' }; - this.socket = connection.socket; - this.connection = connection; - this.framer = null; - - this.connection = connection; - - if (legacy) { - this.readable = this.writable = true; - } -} -util.inherits(Parser, DuplexStream); - -// -// ### function create (connection) -// #### @connection {spdy.Connection} connection -// @constructor wrapper -// -parser.create = function create(connection) { - return new Parser(connection); -}; - -// -// ### function destroy () -// Just a stub. -// -Parser.prototype.destroy = function destroy() { -}; - -// -// ### function _write (data, encoding, cb) -// #### @data {Buffer} chunk of data -// #### @encoding {Null} encoding -// #### @cb {Function} callback -// Writes or buffers data to parser -// -Parser.prototype._write = function write(data, encoding, cb) { - // Legacy compatibility - if (!cb) cb = function() {}; - - if (data !== undefined) { - // Buffer data - this.buffer.push(data); - this.buffered += data.length; - } - - // Notify caller about state (for piping) - if (this.paused) return false; - - // We shall not do anything until we get all expected data - if (this.buffered < this.waiting) return cb(); - - // Mark parser as not drained - if (data !== undefined) this.drained = false; - - var self = this, - buffer = new Buffer(this.waiting), - sliced = 0, - offset = 0; - - while (this.waiting > offset && sliced < this.buffer.length) { - var chunk = this.buffer[sliced++], - overmatched = false; - - // Copy chunk into `buffer` - if (chunk.length > this.waiting - offset) { - chunk.copy(buffer, offset, 0, this.waiting - offset); - - this.buffer[--sliced] = chunk.slice(this.waiting - offset); - this.buffered += this.buffer[sliced].length; - - overmatched = true; - } else { - chunk.copy(buffer, offset); - } - - // Move offset and decrease amount of buffered data - offset += chunk.length; - this.buffered -= chunk.length; - - if (overmatched) break; - } - - // Remove used buffers - this.buffer = this.buffer.slice(sliced); - - // Executed parser for buffered data - this.paused = true; - this.execute(this.state, buffer, function (err, waiting) { - // And unpause once execution finished - self.paused = false; - - // Propagate errors - if (err) { - cb(); - return self.emit('error', err); - } - - // Set new `waiting` - self.waiting = waiting; - - if (self.waiting <= self.buffered) { - self._write(undefined, null, cb); - } else { - process.nextTick(function() { - if (self.drained) return; - - // Mark parser as drained - self.drained = true; - self.emit('drain'); - }); - - cb(); - } - }); -}; - -if (legacy) { - // - // ### function write (data, encoding, cb) - // #### @data {Buffer} chunk of data - // #### @encoding {Null} encoding - // #### @cb {Function} callback - // Legacy method - // - Parser.prototype.write = Parser.prototype._write; - - // - // ### function end () - // Stream's end() implementation - // - Parser.prototype.end = function end() { - this.emit('end'); - }; -} - -// -// ### function createFramer (version) -// #### @version {Number} Protocol version, either 2 or 3 -// Sets framer instance on Parser's instance -// -Parser.prototype.createFramer = function createFramer(version) { - if (spdy.protocol[version]) { - this.emit('version', version); - - this.framer = new spdy.protocol[version].Framer( - spdy.utils.zwrap(this.connection._deflate), - spdy.utils.zwrap(this.connection._inflate) - ); - - // Propagate framer to connection - this.connection._framer = this.framer; - this.emit('framer', this.framer); - } else { - this.emit( - 'error', - new Error('Unknown protocol version requested: ' + version) - ); - } -}; - -// -// ### function execute (state, data, callback) -// #### @state {Object} Parser's state -// #### @data {Buffer} Incoming data -// #### @callback {Function} continuation callback -// Parse buffered data -// -Parser.prototype.execute = function execute(state, data, callback) { - if (state.type === 'frame-head') { - var header = state.header = spdy.protocol.generic.parseHeader(data); - - // Lazily create framer - if (!this.framer && header.control) { - this.createFramer(header.version); - } - - state.type = 'frame-body'; - callback(null, header.length); - } else if (state.type === 'frame-body') { - var self = this; - - // Data frame - if (!state.header.control) { - return onFrame(null, { - type: 'DATA', - id: state.header.id, - fin: (state.header.flags & 0x01) === 0x01, - compressed: (state.header.flags & 0x02) === 0x02, - data: data - }); - } else { - // Control frame - this.framer.execute(state.header, data, onFrame); - } - - function onFrame(err, frame) { - if (err) return callback(err); - - self.emit('frame', frame); - - state.type = 'frame-head'; - callback(null, 8); - }; - } -}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/constants.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/constants.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/constants.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/constants.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,35 @@ +exports.rst = { + PROTOCOL_ERROR: 1, + INVALID_STREAM: 2, + REFUSED_STREAM: 3, + UNSUPPORTED_VERSION: 4, + CANCEL: 5, + INTERNAL_ERROR: 6, + FLOW_CONTROL_ERROR: 7, + STREAM_IN_USE: 8, + STREAM_ALREADY_CLOSED: 9, + INVALID_CREDENTIALS: 10, + FRAME_TOO_LARGE: 11 +}; + +exports.settings = { + FLAG_SETTINGS_PERSIST_VALUE: 1, + FLAG_SETTINGS_PERSISTED: 2, + + SETTINGS_UPLOAD_BANDWIDTH: 1, + SETTINGS_DOWNLOAD_BANDWIDTH: 2, + SETTINGS_ROUND_TRIP_TIME: 3, + SETTINGS_MAX_CONCURRENT_STREAMS: 4, + SETTINGS_CURRENT_CWND: 5, + SETTINGS_DOWNLOAD_RETRANS_RATE: 6, + SETTINGS_INITIAL_WINDOW_SIZE: 7, + SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE: 8 +}; + +exports.DEFAULT_WINDOW = 64 * 1024; + +exports.goaway = { + OK: 0, + PROTOCOL_ERROR: 1, + INTERNAL_ERROR: 2 +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/dictionary.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/dictionary.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/dictionary.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/dictionary.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,203 @@ +var Buffer = require('buffer').Buffer; + +var dictionary = {}; +module.exports = dictionary; + +dictionary[2] = new Buffer([ + 'optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-', + 'languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi', + 'f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser', + '-agent10010120020120220320420520630030130230330430530630740040140240340440', + '5406407408409410411412413414415416417500501502503504505accept-rangesageeta', + 'glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic', + 'ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran', + 'sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati', + 'oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo', + 'ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe', + 'pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic', + 'ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1', + '.1statusversionurl\x00' +].join('')); + +dictionary[3] = new Buffer([ + 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti + 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h + 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p + 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de + 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete.... + 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace... + 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept. + 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep + 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse + 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc + 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding.... + 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l + 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage. + 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep + 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges + 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age. + 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow + 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio + 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac + 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr + 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection + 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont + 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base + 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont + 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding.... + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content- + 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language + 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont + 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng + 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation.. + 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten + 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5... + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content + 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range.. + 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten + 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type.. + 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date.. + 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag.. + 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect + 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi + 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f + 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i + 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match. + 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s + 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince.... + 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none- + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match... + 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang + 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if- + 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi + 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since + 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last + 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie + 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation... + 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for + 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards... + 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma. + 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy + 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent + 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate... + 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza + 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion.... + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range... + 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer + 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr + 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after. + 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve + 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te. + 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail + 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding. + 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra + 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us + 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent + 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary + 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via. + 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni + 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww + 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate.. + 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method + 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get. + 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu + 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200 + 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion.. + 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1 + 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur + 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub + 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s + 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki + 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee + 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive. + 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi + 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012 + 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205 + 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030 + 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043 + 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307 + 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540 + 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084 + 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411 + 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341 + 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164 + 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504 + 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N + 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho + 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative + 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa + 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204. + 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte + 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo + 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm + 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4 + 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40 + 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40 + 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid + 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N + 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found + 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte + 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser + 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro + 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not + 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme + 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503. + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service. + 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila + 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F + 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A + 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J + 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A + 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept. + 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov. + 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0 + 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon + 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W + 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu. + 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa + 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun.. + 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk + 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text. + 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima + 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i + 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg + 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g + 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x + 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x + 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml + 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl + 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text + 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr + 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ + 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat + 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age + 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de + 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd + 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse + 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c + 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i + 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859- + 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-.. + 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0. +]); + +dictionary[3.1] = dictionary[3]; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/framer.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/framer.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/framer.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/framer.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,495 @@ +var spdy = require('../../spdy'); +var util = require('util'); +var Buffer = require('buffer').Buffer; +var EventEmitter = require('events').EventEmitter; +var constants = require('./').constants; + +function Framer() { + EventEmitter.call(this); + + this.version = null; + this.deflate = null; + this.inflate = null; + this.debug = false; +}; +util.inherits(Framer, EventEmitter); +module.exports = Framer; + +Framer.create = function create(version, deflate, inflate) { + return new Framer(version, deflate, inflate); +}; + +// +// ### function setCompression (deflate, inflate) +// #### @deflate {Deflate} +// #### @inflate {Inflate} +// Set framer compression +// +Framer.prototype.setCompression = function setCompresion(deflate, inflate) { + this.deflate = spdy.utils.zwrap(deflate); + this.inflate = spdy.utils.zwrap(inflate); +}; + + +// +// ### function setCompression (deflate, inflate) +// #### @deflate {Deflate} +// #### @inflate {Inflate} +// Set framer compression +// +Framer.prototype.setVersion = function setVersion(version) { + this.version = version; + this.emit('version'); +}; + +// +// internal, converts object into spdy dictionary +// +Framer.prototype.headersToDict = function headersToDict(headers, preprocess) { + function stringify(value) { + if (value !== undefined) { + if (Array.isArray(value)) { + return value.join('\x00'); + } else if (typeof value === 'string') { + return value; + } else { + return value.toString(); + } + } else { + return ''; + } + } + + // Lower case of all headers keys + var loweredHeaders = {}; + Object.keys(headers || {}).map(function(key) { + loweredHeaders[key.toLowerCase()] = headers[key]; + }); + + // Allow outer code to add custom headers or remove something + if (preprocess) + preprocess(loweredHeaders); + + // Transform object into kv pairs + var size = this.version === 2 ? 2 : 4, + len = size, + pairs = Object.keys(loweredHeaders).filter(function(key) { + var lkey = key.toLowerCase(); + return lkey !== 'connection' && lkey !== 'keep-alive' && + lkey !== 'proxy-connection' && lkey !== 'transfer-encoding'; + }).map(function(key) { + var klen = Buffer.byteLength(key), + value = stringify(loweredHeaders[key]), + vlen = Buffer.byteLength(value); + + len += size * 2 + klen + vlen; + return [klen, key, vlen, value]; + }), + result = new Buffer(len); + + if (this.version === 2) + result.writeUInt16BE(pairs.length, 0, true); + else + result.writeUInt32BE(pairs.length, 0, true); + + var offset = size; + pairs.forEach(function(pair) { + // Write key length + if (this.version === 2) + result.writeUInt16BE(pair[0], offset, true); + else + result.writeUInt32BE(pair[0], offset, true); + // Write key + result.write(pair[1], offset + size); + + offset += pair[0] + size; + + // Write value length + if (this.version === 2) + result.writeUInt16BE(pair[2], offset, true); + else + result.writeUInt32BE(pair[2], offset, true); + // Write value + result.write(pair[3], offset + size); + + offset += pair[2] + size; + }, this); + + return result; +}; + +Framer.prototype._synFrame = function _synFrame(type, + id, + assoc, + priority, + dict, + callback) { + var self = this; + + // Compress headers + this.deflate(dict, function (err, chunks, size) { + if (err) + return callback(err); + + var offset = type === 'SYN_STREAM' ? 18 : self.version === 2 ? 14 : 12, + total = offset - 8 + size, + frame = new Buffer(offset + size); + + // Control + Version + frame.writeUInt16BE(0x8000 | self.version, 0, true); + // Type + frame.writeUInt16BE(type === 'SYN_STREAM' ? 1 : 2, 2, true); + // Size + frame.writeUInt32BE(total & 0x00ffffff, 4, true); + // Stream ID + frame.writeUInt32BE(id & 0x7fffffff, 8, true); + + if (type === 'SYN_STREAM') { + // Unidirectional + if (assoc !== 0) + frame[4] = 2; + + // Associated Stream-ID + frame.writeUInt32BE(assoc & 0x7fffffff, 12, true); + + // Priority + var priorityValue; + if (self.version === 2) + priorityValue = Math.max(Math.min(priority, 3), 0) << 6; + else + priorityValue = Math.max(Math.min(priority, 7), 0) << 5; + frame.writeUInt8(priorityValue, 16, true); + } + + for (var i = 0; i < chunks.length; i++) { + chunks[i].copy(frame, offset); + offset += chunks[i].length; + } + + callback(null, frame); + }); +}; + +// +// ### function replyFrame (id, code, reason, headers, callback) +// #### @id {Number} Stream ID +// #### @code {Number} HTTP Status Code +// #### @reason {String} (optional) +// #### @headers {Object|Array} (optional) HTTP headers +// #### @callback {Function} Continuation function +// Sends SYN_REPLY frame +// +Framer.prototype.replyFrame = function replyFrame(id, + code, + reason, + headers, + callback) { + if (!this.version) { + return this.on('version', function() { + this.replyFrame(id, code, reason, headers, callback); + }); + } + + var self = this; + var dict = this.headersToDict(headers, function(headers) { + if (self.version === 2) { + headers.status = code + ' ' + reason; + headers.version = 'HTTP/1.1'; + } else { + headers[':status'] = code + ' ' + reason; + headers[':version'] = 'HTTP/1.1'; + } + }); + + + this._synFrame('SYN_REPLY', id, null, 0, dict, callback); +}; + +// +// ### function streamFrame (id, assoc, headers, callback) +// #### @id {Number} stream id +// #### @assoc {Number} associated stream id +// #### @meta {Object} meta headers ( method, scheme, url, version ) +// #### @headers {Object} stream headers +// #### @callback {Function} continuation callback +// Create SYN_STREAM frame +// (needed for server push and testing) +// +Framer.prototype.streamFrame = function streamFrame(id, + assoc, + meta, + headers, + callback) { + if (!this.version) { + return this.on('version', function() { + this.streamFrame(id, assoc, meta, headers, callback); + }); + } + + var self = this; + var dict = this.headersToDict(headers, function(headers) { + if (self.version === 2) { + if (meta.status) + headers.status = meta.status; + headers.version = meta.version || 'HTTP/1.1'; + headers.url = meta.url; + if (meta.method) + headers.method = meta.method; + } else { + if (meta.status) + headers[':status'] = meta.status; + headers[':version'] = meta.version || 'HTTP/1.1'; + headers[':path'] = meta.path || meta.url; + headers[':scheme'] = meta.scheme || 'https'; + headers[':host'] = meta.host; + if (meta.method) + headers[':method'] = meta.method; + } + }); + + this._synFrame('SYN_STREAM', id, assoc, meta.priority, dict, callback); +}; + +// +// ### function headersFrame (id, headers, callback) +// #### @id {Number} Stream id +// #### @headers {Object} Headers +// #### @callback {Function} +// Sends HEADERS frame +// +Framer.prototype.headersFrame = function headersFrame(id, headers, callback) { + if (!this.version) { + return this.on('version', function() { + this.headersFrame(id, headers, callback); + }); + } + + var self = this; + var dict = this.headersToDict(headers, function(headers) {}); + + this.deflate(dict, function (err, chunks, size) { + if (err) + return callback(err); + + var offset = self.version === 2 ? 14 : 12, + total = offset - 8 + size, + frame = new Buffer(offset + size); + + // Control + Version + frame.writeUInt16BE(0x8000 | self.version, 0, true); + // Type + frame.writeUInt16BE(8, 2, true); + // Length + frame.writeUInt32BE(total & 0x00ffffff, 4, true); + // Stream ID + frame.writeUInt32BE(id & 0x7fffffff, 8, true); + + // Copy chunks + for (var i = 0; i < chunks.length; i++) { + chunks[i].copy(frame, offset); + offset += chunks[i].length; + } + + callback(null, frame); + }); +}; + +// +// ### function dataFrame (id, fin, data, callback) +// #### @id {Number} Stream id +// #### @fin {Bool} Is this data frame last frame +// #### @data {Buffer} Response data +// #### @callback {Function} +// Sends DATA frame +// +Framer.prototype.dataFrame = function dataFrame(id, fin, data, callback) { + if (!this.version) { + return this.on('version', function() { + this.dataFrame(id, fin, data, callback); + }); + } + + if (!fin && !data.length) + return callback(null, []); + + var frame = new Buffer(8 + data.length); + + frame.writeUInt32BE(id & 0x7fffffff, 0, true); + frame.writeUInt32BE(data.length & 0x00ffffff, 4, true); + frame.writeUInt8(fin ? 0x01 : 0x0, 4, true); + + if (data.length) + data.copy(frame, 8); + + return callback(null, frame); +}; + +// +// ### function pingFrame (id) +// #### @id {Number} Ping ID +// Sends PING frame +// +Framer.prototype.pingFrame = function pingFrame(id, callback) { + if (!this.version) { + return this.on('version', function() { + this.pingFrame(id, callback); + }); + } + + var header = new Buffer(12); + + // Version and type + header.writeUInt32BE(0x80000006 | (this.version << 16), 0, true); + // Length + header.writeUInt32BE(0x00000004, 4, true); + // ID + header.writeUInt32BE(id, 8, true); + + return callback(null, header); +}; + +// +// ### function rstFrame (id, code, extra, callback) +// #### @id {Number} Stream ID +// #### @code {Number} RST Code +// #### @extra {String} Extra debugging info +// #### @callback {Function} +// Sends PING frame +// +Framer.prototype.rstFrame = function rstFrame(id, code, extra, callback) { + if (!this.version) { + return this.on('version', function() { + this.rstFrame(id, code, extra, callback); + }); + } + + var header = new Buffer(16 + + (this.debug ? Buffer.byteLength(extra || '') : 0)); + + // Version and type + header.writeUInt32BE(0x80000003 | (this.version << 16), 0, true); + // Length + header.writeUInt32BE(0x00000008, 4, true); + // Stream ID + header.writeUInt32BE(id & 0x7fffffff, 8, true); + // Status Code + header.writeUInt32BE(code, 12, true); + + // Extra debugging information + if (this.debug && extra) + header.write(extra, 16); + + return callback(null, header); +}; + +// +// ### function settingsFrame (options, callback) +// #### @options {Object} settings frame options +// #### @callback {Function} +// Sends SETTINGS frame with MAX_CONCURRENT_STREAMS and initial window +// +Framer.prototype.settingsFrame = function settingsFrame(options, callback) { + if (!this.version) { + return this.on('version', function() { + this.settingsFrame(options, callback); + }); + } + + var settings, + key = this.version === 2 ? '2/' + options.maxStreams : + '3/' + options.maxStreams + ':' + + options.windowSize; + + if (!(settings = Framer.settingsCache[key])) { + var params = []; + if (isFinite(options.maxStreams)) { + params.push({ + key: constants.settings.SETTINGS_MAX_CONCURRENT_STREAMS, + value: options.maxStreams + }); + } + if (this.version > 2) { + params.push({ + key: constants.settings.SETTINGS_INITIAL_WINDOW_SIZE, + value: options.windowSize + }); + } + + settings = new Buffer(12 + 8 * params.length); + + // Version and type + settings.writeUInt32BE(0x80000004 | (this.version << 16), 0, true); + // Length + settings.writeUInt32BE((4 + 8 * params.length) & 0x00FFFFFF, 4, true); + // Count of entries + settings.writeUInt32BE(params.length, 8, true); + + var offset = 12; + params.forEach(function(param) { + var flag = constants.settings.FLAG_SETTINGS_PERSIST_VALUE << 24; + + if (this.version === 2) + settings.writeUInt32LE(flag | param.key, offset, true); + else + settings.writeUInt32BE(flag | param.key, offset, true); + offset += 4; + settings.writeUInt32BE(param.value & 0x7fffffff, offset, true); + offset += 4; + }, this); + + Framer.settingsCache[key] = settings; + } + + return callback(null, settings); +}; +Framer.settingsCache = {}; + +// +// ### function windowUpdateFrame (id) +// #### @id {Buffer} WindowUpdate ID +// Sends WINDOW_UPDATE frame +// +Framer.prototype.windowUpdateFrame = function windowUpdateFrame(id, delta, cb) { + if (!this.version) { + return this.on('version', function() { + this.windowUpdateFrame(id, delta, cb); + }); + } + + var header = new Buffer(16); + + // Version and type + header.writeUInt32BE(0x80000009 | (this.version << 16), 0, true); + // Length + header.writeUInt32BE(0x00000008, 4, true); + // ID + header.writeUInt32BE(id & 0x7fffffff, 8, true); + // Delta + if (delta > 0) + header.writeUInt32BE(delta & 0x7fffffff, 12, true); + else + header.writeUInt32BE(delta, 12, true); + + return cb(null, header); +}; + +Framer.prototype.goawayFrame = function goawayFrame(lastId, status, cb) { + if (!this.version) { + return this.on('version', function() { + this.goawayFrame(lastId, status, cb); + }); + } + + var header = new Buffer(16); + + // Version and type + header.writeUInt32BE(0x80000007 | (this.version << 16), 0, true); + // Length + header.writeUInt32BE(0x00000008, 4, true); + // Last-good-stream-ID + header.writeUInt32BE(lastId & 0x7fffffff, 8, true); + // Status + header.writeUInt32BE(status, 12, true); + + return cb(null, header); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/generic.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/generic.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/generic.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/generic.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -// -// ### function parseHeader (data) -// ### @data {Buffer} incoming data -// Returns parsed SPDY frame header -// -exports.parseHeader = function parseHeader(data) { - var header = { - control: (data.readUInt8(0) & 0x80) === 0x80 ? true : false, - version: null, - type: null, - id: null, - flags: data.readUInt8(4), - length: data.readUInt32BE(4) & 0x00ffffff - }; - - if (header.control) { - header.version = data.readUInt16BE(0) & 0x7fff; - header.type = data.readUInt16BE(2); - } else { - header.id = data.readUInt32BE(0) & 0x7fffffff; - } - - return header; -}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/index.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/index.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/index.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/index.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,4 @@ +exports.dictionary = require('./dictionary'); +exports.constants = require('./constants'); +exports.parser = require('./parser'); +exports.framer = require('./framer'); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/parser.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/parser.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/parser.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/parser.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,565 @@ +var parser = exports; + +var spdy = require('../../spdy'), + utils = spdy.utils, + util = require('util'), + stream = require('stream'), + Buffer = require('buffer').Buffer; + +var legacy = !stream.Duplex; + +if (legacy) { + var DuplexStream = stream; +} else { + var DuplexStream = stream.Duplex; +} + +// +// ### function Parser (connection) +// #### @connection {spdy.Connection} connection +// SPDY protocol frames parser's @constructor +// +function Parser(connection) { + DuplexStream.call(this); + + this.paused = false; + this.buffer = []; + this.buffered = 0; + this.waiting = 8; + + this.state = { type: 'frame-head' }; + this.socket = connection.socket; + this.connection = connection; + + this.version = null; + this.deflate = null; + this.inflate = null; + + this.connection = connection; + + if (legacy) { + this.readable = this.writable = true; + } +} +util.inherits(Parser, DuplexStream); + +// +// ### function create (connection) +// #### @connection {spdy.Connection} connection +// @constructor wrapper +// +parser.create = function create(connection) { + return new Parser(connection); +}; + +// +// ### function destroy () +// Just a stub. +// +Parser.prototype.destroy = function destroy() { +}; + +// +// ### function _write (data, encoding, cb) +// #### @data {Buffer} chunk of data +// #### @encoding {Null} encoding +// #### @cb {Function} callback +// Writes or buffers data to parser +// +Parser.prototype._write = function write(data, encoding, cb) { + // Legacy compatibility + if (!cb) cb = function() {}; + + if (data !== undefined) { + // Buffer data + this.buffer.push(data); + this.buffered += data.length; + } + + // Notify caller about state (for piping) + if (this.paused) { + this.needDrain = true; + cb(); + return false; + } + + // We shall not do anything until we get all expected data + if (this.buffered < this.waiting) { + if (this.needDrain) { + // Mark parser as drained + this.needDrain = false; + this.emit('drain'); + } + + cb(); + return; + } + + var self = this, + buffer = new Buffer(this.waiting), + sliced = 0, + offset = 0; + + while (this.waiting > offset && sliced < this.buffer.length) { + var chunk = this.buffer[sliced++], + overmatched = false; + + // Copy chunk into `buffer` + if (chunk.length > this.waiting - offset) { + chunk.copy(buffer, offset, 0, this.waiting - offset); + + this.buffer[--sliced] = chunk.slice(this.waiting - offset); + this.buffered += this.buffer[sliced].length; + + overmatched = true; + } else { + chunk.copy(buffer, offset); + } + + // Move offset and decrease amount of buffered data + offset += chunk.length; + this.buffered -= chunk.length; + + if (overmatched) break; + } + + // Remove used buffers + this.buffer = this.buffer.slice(sliced); + + // Executed parser for buffered data + this.paused = true; + var sync = true; + this.execute(this.state, buffer, function (err, waiting) { + // Propagate errors + if (err) { + // And unpause once execution finished + self.paused = false; + + cb(); + return self.emit('error', err); + } + + // Set new `waiting` + self.waiting = waiting; + + if (sync) { + utils.nextTick(function() { + // Unpause right before entering new `_write()` call + self.paused = false; + self._write(undefined, null, cb); + }); + } else { + // Unpause right before entering new `_write()` call + self.paused = false; + self._write(undefined, null, cb); + } + }); + sync = false; +}; + +if (legacy) { + // + // ### function write (data, encoding, cb) + // #### @data {Buffer} chunk of data + // #### @encoding {Null} encoding + // #### @cb {Function} callback + // Legacy method + // + Parser.prototype.write = Parser.prototype._write; + + // + // ### function end () + // Stream's end() implementation + // + Parser.prototype.end = function end() { + this.emit('end'); + }; +} + +// +// ### function setVersion (version) +// #### @version {Number} Protocol version +// Set protocol version to use +// +Parser.prototype.setVersion = function setVersion(version) { + this.version = version; + this.emit('version', version); + this.deflate = spdy.utils.zwrap(this.connection._spdyState.deflate); + this.inflate = spdy.utils.zwrap(this.connection._spdyState.inflate); +}; + +// +// ### function execute (state, data, callback) +// #### @state {Object} Parser's state +// #### @data {Buffer} Incoming data +// #### @callback {Function} continuation callback +// Parse buffered data +// +Parser.prototype.execute = function execute(state, data, callback) { + if (state.type === 'frame-head') { + var header = state.header = this.parseHeader(data); + + if (this.version === null && header.control) { + if (header.version !== 2 && header.version !== 3) { + return callback(new Error('Unsupported spdy version: ' + + header.version)); + } + this.setVersion(header.version); + } + + state.type = 'frame-body'; + callback(null, header.length); + } else if (state.type === 'frame-body') { + var self = this; + + // Data frame + if (!state.header.control) { + return onFrame(null, { + type: 'DATA', + id: state.header.id, + fin: (state.header.flags & 0x01) === 0x01, + compressed: (state.header.flags & 0x02) === 0x02, + data: data + }); + } else { + // Control frame + this.parseBody(state.header, data, onFrame); + } + + function onFrame(err, frame) { + if (err) return callback(err); + + self.emit('frame', frame); + + state.type = 'frame-head'; + callback(null, 8); + }; + } +}; + + +// +// ### function parseHeader (data) +// ### @data {Buffer} incoming data +// Returns parsed SPDY frame header +// +Parser.prototype.parseHeader = function parseHeader(data) { + var header = { + control: (data.readUInt8(0) & 0x80) === 0x80 ? true : false, + version: null, + type: null, + id: null, + flags: data.readUInt8(4), + length: data.readUInt32BE(4) & 0x00ffffff + }; + + if (header.control) { + header.version = data.readUInt16BE(0) & 0x7fff; + header.type = data.readUInt16BE(2); + } else { + header.id = data.readUInt32BE(0) & 0x7fffffff; + } + + return header; +}; + + +// +// ### function execute (header, body, callback) +// #### @header {Object} Frame headers +// #### @body {Buffer} Frame's body +// #### @callback {Function} Continuation callback +// Parse frame (decompress data and create streams) +// +Parser.prototype.parseBody = function parseBody(header, body, callback) { + // SYN_STREAM or SYN_REPLY + if (header.type === 0x01 || header.type === 0x02) + this.parseSynHead(header.type, header.flags, body, callback); + // RST_STREAM + else if (header.type === 0x03) + this.parseRst(body, callback); + // SETTINGS + else if (header.type === 0x04) + this.parseSettings(body, callback); + else if (header.type === 0x05) + callback(null, { type: 'NOOP' }); + // PING + else if (header.type === 0x06) + this.parsePing(body, callback); + // GOAWAY + else if (header.type === 0x07) + this.parseGoaway(body, callback); + // HEADERS + else if (header.type === 0x08) + this.parseHeaders(body, callback); + // WINDOW_UPDATE + else if (header.type === 0x09) + this.parseWindowUpdate(body, callback); + // X-FORWARDED + else if (header.type === 0xf000) + this.parseXForwarded(body, callback); + else + callback(null, { type: 'unknown: ' + header.type, body: body }); +}; + + +// +// ### function parseSynHead (type, flags, data) +// #### @type {Number} Frame type +// #### @flags {Number} Frame flags +// #### @data {Buffer} input data +// Returns parsed syn_* frame's head +// +Parser.prototype.parseSynHead = function parseSynHead(type, + flags, + data, + callback) { + var stream = type === 0x01; + var offset = stream ? 10 : this.version === 2 ? 6 : 4; + + if (data.length < offset) + return callback(new Error('SynHead OOB')); + + var kvs = data.slice(offset); + this.parseKVs(kvs, function(err, headers) { + if (err) + return callback(err); + + if (stream === 'SYN_STREAM' && + (!headers.method || !(headers.path || headers.url))) { + return callback(new Error('Missing `:method` and/or `:path` header')); + } + + callback(null, { + type: stream ? 'SYN_STREAM' : 'SYN_REPLY', + id: data.readUInt32BE(0, true) & 0x7fffffff, + associated: stream ? data.readUInt32BE(4, true) & 0x7fffffff : 0, + priority: stream ? data[8] >> 5 : 0, + fin: (flags & 0x01) === 0x01, + unidir: (flags & 0x02) === 0x02, + headers: headers, + url: headers.path || headers.url || '' + }); + }); +}; + + +// +// ### function parseHeaders (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse HEADERS +// +Parser.prototype.parseHeaders = function parseHeaders(data, callback) { + var offset = this.version === 2 ? 6 : 4; + if (data.length < offset) + return callback(new Error('HEADERS OOB')); + + var streamId = data.readUInt32BE(0, true) & 0x7fffffff; + + this.parseKVs(data.slice(offset), function(err, headers) { + if (err) + return callback(err); + + callback(null, { + type: 'HEADERS', + id: streamId, + headers: headers + }); + }); +}; + + +// +// ### function parseKVs (pairs, callback) +// #### @pairs {Buffer} header pairs +// #### @callback {Function} continuation +// Returns hashmap of parsed headers +// +Parser.prototype.parseKVs = function parseKVs(pairs, callback) { + var self = this; + this.inflate(pairs, function(err, chunks, length) { + if (err) + return callback(err); + + var pairs = Buffer.concat(chunks, length); + + var size = self.version === 2 ? 2 : 4; + if (pairs.length < size) + return callback(new Error('KV OOB')); + + var count = size === 2 ? pairs.readUInt16BE(0, true) : + pairs.readUInt32BE(0, true), + headers = {}; + + pairs = pairs.slice(size); + + function readString() { + if (pairs.length < size) + return null; + var len = size === 2 ? pairs.readUInt16BE(0, true) : + pairs.readUInt32BE(0, true); + + if (pairs.length < size + len) { + return null; + } + var value = pairs.slice(size, size + len); + + pairs = pairs.slice(size + len); + + return value.toString(); + } + + while(count > 0) { + var key = readString(), + value = readString(); + + if (key === null || value === null) + return callback(new Error('Headers OOB')); + + if (self.version >= 3) + headers[key.replace(/^:/, '')] = value; + else + headers[key] = value; + count--; + } + + callback(null, headers); + }); +}; + + +// +// ### function parseRst (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse RST +// +Parser.prototype.parseRst = function parseRst(data, callback) { + if (data.length < 8) + return callback(new Error('RST OOB')); + + callback(null, { + type: 'RST_STREAM', + id: data.readUInt32BE(0, true) & 0x7fffffff, + status: data.readUInt32BE(4, true), + extra: data.length > 8 ? data.slice(8) : null + }); +}; + + +// +// ### function parseSettings (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse SETTINGS +// +Parser.prototype.parseSettings = function parseSettings(data, callback) { + if (data.length < 4) + return callback(new Error('SETTINGS OOB')); + + var settings = {}, + number = data.readUInt32BE(0, true), + idMap = { + 1: 'upload_bandwidth', + 2: 'download_bandwidth', + 3: 'round_trip_time', + 4: 'max_concurrent_streams', + 5: 'current_cwnd', + 6: 'download_retrans_rate', + 7: 'initial_window_size', + 8: 'client_certificate_vector_size' + }; + + if (data.length < 4 + number * 8) + return callback(new Error('SETTINGS OOB#2')); + + for (var i = 0; i < number; i++) { + var id = (this.version === 2 ? data.readUInt32LE(4 + i * 8, true) : + data.readUInt32BE(4 + i * 8, true)), + flags = (id >> 24) & 0xff; + id = id & 0xffffff; + + var name = idMap[id]; + + settings[id] = settings[name] = { + persist: !!(flags & 0x1), + persisted: !!(flags & 0x2), + value: data.readUInt32BE(8 + (i*8), true) + }; + } + + callback(null, { + type: 'SETTINGS', + settings: settings + }); +}; + + +// +// ### function parseGoaway (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse PING +// +Parser.prototype.parsePing = function parsePing(body, callback) { + if (body.length < 4) + return callback(new Error('PING OOB')); + callback(null, { type: 'PING', pingId: body.readUInt32BE(0, true) }); +}; + + +// +// ### function parseGoaway (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse GOAWAY +// +Parser.prototype.parseGoaway = function parseGoaway(data, callback) { + if (data.length < 4) + return callback(new Error('GOAWAY OOB')); + + callback(null, { + type: 'GOAWAY', + lastId: data.readUInt32BE(0, true) & 0x7fffffff + }); +}; + + +// +// ### function parseWindowUpdate (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse WINDOW_UPDATE +// +Parser.prototype.parseWindowUpdate = function parseWindowUpdate(data, callback) { + if (data.length < 8) + return callback(new Error('WINDOW_UPDATE OOB')); + + callback(null, { + type: 'WINDOW_UPDATE', + id: data.readUInt32BE(0, true) & 0x7fffffff, + delta: data.readUInt32BE(4, true) & 0x7fffffff + }); +}; + + +// +// ### function parseXForwarded (data, callback) +// #### @data {Buffer} input data +// #### @callback {Function} continuation +// Parse X_FORWARDED +// +Parser.prototype.parseXForwarded = function parseXForwarded(data, callback) { + if (data.length < 4) + return callback(new Error('X_FORWARDED OOB')); + + var len = data.readUInt32BE(0, true); + if (len + 4 > data.length) + return callback(new Error('X_FORWARDED host length OOB')); + + callback(null, { + type: 'X_FORWARDED', + host: data.slice(4, 4 + len).toString() + }); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/dictionary.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/dictionary.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/dictionary.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/dictionary.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -exports.dictionary = new Buffer([ - 'optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-', - 'languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi', - 'f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser', - '-agent10010120020120220320420520630030130230330430530630740040140240340440', - '5406407408409410411412413414415416417500501502503504505accept-rangesageeta', - 'glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic', - 'ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran', - 'sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati', - 'oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo', - 'ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe', - 'pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic', - 'ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1', - '.1statusversionurl\x00' -].join('')); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/framer.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/framer.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/framer.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/framer.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,286 +0,0 @@ -var framer = exports; - -var spdy = require('../../../spdy'), - Buffer = require('buffer').Buffer, - protocol = require('./'); - -// -// ### function Framer (deflate, inflate) -// #### @deflate {zlib.Deflate} Deflate stream -// #### @inflate {zlib.Inflate} Inflate stream -// Framer constructor -// -function Framer(deflate, inflate) { - this.version = 2; - this.deflate = deflate; - this.inflate = inflate; -} -exports.Framer = Framer; - - -// -// ### function execute (header, body, callback) -// #### @header {Object} Frame headers -// #### @body {Buffer} Frame's body -// #### @callback {Function} Continuation callback -// Parse frame (decompress data and create streams) -// -Framer.prototype.execute = function execute(header, body, callback) { - // SYN_STREAM or SYN_REPLY - if (header.type === 0x01 || header.type === 0x02) { - var frame = protocol.parseSynHead(header.type, header.flags, body); - - body = body.slice(frame._offset); - - this.inflate(body, function(err, chunks, length) { - if (err) return callback(err); - - var pairs = new Buffer(length); - for (var i = 0, offset = 0; i < chunks.length; i++) { - chunks[i].copy(pairs, offset); - offset += chunks[i].length; - } - - frame.headers = protocol.parseHeaders(pairs); - frame.url = frame.headers.url || ''; - - callback(null, frame); - }); - // RST_STREAM - } else if (header.type === 0x03) { - callback(null, protocol.parseRst(body)); - // SETTINGS - } else if (header.type === 0x04) { - callback(null, { type: 'SETTINGS' }); - } else if (header.type === 0x05) { - callback(null, { type: 'NOOP' }); - // PING - } else if (header.type === 0x06) { - callback(null, { type: 'PING', pingId: body }); - // GOAWAY - } else if (header.type === 0x07) { - callback(null, protocol.parseGoaway(body)); - } else { - callback(null, { type: 'unknown: ' + header.type, body: body }); - } -}; - -// -// internal, converts object into spdy dictionary -// -function headersToDict(headers, preprocess) { - function stringify(value) { - if (value !== undefined) { - if (Array.isArray(value)) { - return value.join('\x00'); - } else if (typeof value === 'string') { - return value; - } else { - return value.toString(); - } - } else { - return ''; - } - } - - // Lower case of all headers keys - var loweredHeaders = {}; - Object.keys(headers || {}).map(function(key) { - loweredHeaders[key.toLowerCase()] = headers[key]; - }); - - // Allow outer code to add custom headers or remove something - if (preprocess) preprocess(loweredHeaders); - - // Transform object into kv pairs - var len = 2, - pairs = Object.keys(loweredHeaders).filter(function(key) { - var lkey = key.toLowerCase(); - return lkey !== 'connection' && lkey !== 'keep-alive' && - lkey !== 'proxy-connection' && lkey !== 'transfer-encoding'; - }).map(function(key) { - var klen = Buffer.byteLength(key), - value = stringify(loweredHeaders[key]), - vlen = Buffer.byteLength(value); - - len += 4 + klen + vlen; - return [klen, key, vlen, value]; - }), - result = new Buffer(len); - - result.writeUInt16BE(pairs.length, 0, true); - - var offset = 2; - pairs.forEach(function(pair) { - // Write key length - result.writeUInt16BE(pair[0], offset, true); - // Write key - result.write(pair[1], offset + 2); - - offset += pair[0] + 2; - - // Write value length - result.writeUInt16BE(pair[2], offset, true); - // Write value - result.write(pair[3], offset + 2); - - offset += pair[2] + 2; - }); - - return result; -}; - -Framer.prototype._synFrame = function _synFrame(type, id, assoc, priority, dict, - callback) { - // Compress headers - this.deflate(dict, function (err, chunks, size) { - if (err) return callback(err); - - var offset = type === 'SYN_STREAM' ? 18 : 14, - total = (type === 'SYN_STREAM' ? 10 : 6) + size, - frame = new Buffer(offset + size);; - - frame.writeUInt16BE(0x8002, 0, true); // Control + Version - frame.writeUInt16BE(type === 'SYN_STREAM' ? 1 : 2, 2, true); // type - frame.writeUInt32BE(total & 0x00ffffff, 4, true); // No flag support - frame.writeUInt32BE(id & 0x7fffffff, 8, true); // Stream-ID - - if (type === 'SYN_STREAM') { - frame[4] = 2; - frame.writeUInt32BE(assoc & 0x7fffffff, 12, true); // Stream-ID - } - - frame.writeUInt8(priority & 0x3, 16, true); // Priority - - for (var i = 0; i < chunks.length; i++) { - chunks[i].copy(frame, offset); - offset += chunks[i].length; - } - - callback(null, frame); - }); -}; - -// -// ### function replyFrame (id, code, reason, headers, callback) -// #### @id {Number} Stream ID -// #### @code {Number} HTTP Status Code -// #### @reason {String} (optional) -// #### @headers {Object|Array} (optional) HTTP headers -// #### @callback {Function} Continuation function -// Sends SYN_REPLY frame -// -Framer.prototype.replyFrame = function replyFrame(id, code, reason, headers, - callback) { - var dict = headersToDict(headers, function(headers) { - headers.status = code + ' ' + reason; - headers.version = 'HTTP/1.1'; - }); - - this._synFrame('SYN_REPLY', id, null, 0, dict, callback); -}; - -// -// ### function streamFrame (id, assoc, headers, callback) -// #### @id {Number} stream id -// #### @assoc {Number} associated stream id -// #### @meta {Object} meta headers ( method, scheme, url, version ) -// #### @headers {Object} stream headers -// #### @callback {Function} continuation callback -// Create SYN_STREAM frame -// (needed for server push and testing) -// -Framer.prototype.streamFrame = function streamFrame(id, assoc, meta, headers, - callback) { - var dict = headersToDict(headers, function(headers) { - headers.status = 200; - headers.version = 'HTTP/1.1'; - headers.url = meta.url; - }); - - this._synFrame('SYN_STREAM', id, assoc, meta.priority, dict, callback); -}; - -// -// ### function dataFrame (id, fin, data) -// #### @id {Number} Stream id -// #### @fin {Bool} Is this data frame last frame -// #### @data {Buffer} Response data -// Sends DATA frame -// -Framer.prototype.dataFrame = function dataFrame(id, fin, data) { - if (!fin && !data.length) return []; - - var frame = new Buffer(8 + data.length); - - frame.writeUInt32BE(id & 0x7fffffff, 0, true); - frame.writeUInt32BE(data.length & 0x00ffffff, 4, true); - frame.writeUInt8(fin ? 0x01 : 0x0, 4, true); - - if (data.length) data.copy(frame, 8); - - return frame; -}; - -// -// ### function pingFrame (id) -// #### @id {Buffer} Ping ID -// Sends PING frame -// -Framer.prototype.pingFrame = function pingFrame(id) { - var header = new Buffer(12); - - header.writeUInt32BE(0x80020006, 0, true); // Version and type - header.writeUInt32BE(0x00000004, 4, true); // Length - id.copy(header, 8, 0, 4); // ID - - return header; -}; - -// -// ### function rstFrame (id, code) -// #### @id {Number} Stream ID -// #### @code {NUmber} RST Code -// Sends PING frame -// -Framer.prototype.rstFrame = function rstFrame(id, code) { - var header; - - if (!(header = Framer.rstCache[code])) { - header = new Buffer(16); - - header.writeUInt32BE(0x80020003, 0, true); // Version and type - header.writeUInt32BE(0x00000008, 4, true); // Length - header.writeUInt32BE(id & 0x7fffffff, 8, true); // Stream ID - header.writeUInt32BE(code, 12, true); // Status Code - - Framer.rstCache[code] = header; - } - - return header; -}; -Framer.rstCache = {}; - -// -// ### function settingsFrame (options) -// #### @options {Object} settings frame options -// Sends SETTINGS frame with MAX_CONCURRENT_STREAMS -// -Framer.prototype.settingsFrame = function settingsFrame(options) { - var settings; - - if (!(settings = Framer.settingsCache[options.maxStreams])) { - settings = new Buffer(20); - - settings.writeUInt32BE(0x80020004, 0, true); // Version and type - settings.writeUInt32BE(0x0000000C, 4, true); // length - settings.writeUInt32BE(0x00000001, 8, true); // Count of entries - settings.writeUInt32LE(0x01000004, 12, true); // Entry ID and Persist flag - settings.writeUInt32BE(options.maxStreams, 16, true); - - Framer.settingsCache[options.maxStreams] = settings; - } - - return settings; -}; -Framer.settingsCache = {}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/index.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/index.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/index.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/index.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -var v2; - -try { - v2 = require('./protocol.node'); -} catch (e) { - v2 = require('./protocol.js'); -} -module.exports = v2; - -v2.Framer = require('./framer').Framer; - -v2.dictionary = require('./dictionary').dictionary; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/protocol.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/protocol.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/protocol.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v2/protocol.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -var protocol = exports; - -// -// ### function parseSynHead (type, flags, data) -// #### @type {Number} Frame type -// #### @flags {Number} Frame flags -// #### @data {Buffer} input data -// Returns parsed syn_* frame's head -// -protocol.parseSynHead = function parseSynHead(type, flags, data) { - var stream = type === 0x01; - - return { - type: stream ? 'SYN_STREAM' : 'SYN_REPLY', - id: data.readUInt32BE(0, true) & 0x7fffffff, - version: 2, - associated: stream ? data.readUInt32BE(4, true) & 0x7fffffff : 0, - priority: stream ? data[8] >> 6 : 0, - fin: (flags & 0x01) === 0x01, - unidir: (flags & 0x02) === 0x02, - _offset: stream ? 10 : 6 - }; -}; - -// -// ### function parseHeaders (pairs) -// #### @pairs {Buffer} header pairs -// Returns hashmap of parsed headers -// -protocol.parseHeaders = function parseHeaders(pairs) { - var count = pairs.readUInt16BE(0, true), - headers = {}; - - pairs = pairs.slice(2); - - function readString() { - var len = pairs.readUInt16BE(0, true), - value = pairs.slice(2, 2 + len); - - pairs = pairs.slice(2 + len); - - return value.toString(); - } - - while(count > 0) { - headers[readString()] = readString(); - count--; - } - - return headers; -}; - -// -// ### function parsesRst frame -protocol.parseRst = function parseRst(data) { - return { - type: 'RST_STREAM', - id: data.readUInt32BE(0, true) & 0x7fffffff, - status: data.readUInt32BE(4, true) - }; -}; - -protocol.parseGoaway = function parseGoaway(data) { - return { - type: 'GOAWAY', - lastId: data.readUInt32BE(0, true) & 0x7fffffff - }; -}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/dictionary.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/dictionary.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/dictionary.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/dictionary.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -exports.dictionary = new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, - 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, - 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, - 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, - 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, - 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, - 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, - 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, - 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, - 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, - 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, - 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, - 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, - 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, - 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, - 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, - 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, - 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, - 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, - 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, - 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, - 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, - 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, - 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, - 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, - 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, - 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, - 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, - 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, - 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, - 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, - 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, - 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, - 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, - 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, - 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, - 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, - 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, - 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, - 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, - 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, - 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, - 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, - 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, - 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, - 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, - 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, - 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, - 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, - 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, - 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, - 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, - 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, - 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, - 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, - 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, - 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, - 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, - 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, - 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, - 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, - 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, - 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, - 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, - 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, - 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, - 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, - 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, - 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, - 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, - 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, - 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, - 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, - 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, - 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, - 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, - 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, - 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, - 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, - 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, - 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, - 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, - 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, - 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, - 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, - 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, - 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, - 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, - 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, - 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, - 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, - 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, - 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, - 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, - 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, - 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, - 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, - 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, - 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, - 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, - 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, - 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, - 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, - 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, - 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, - 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, - 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, - 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, - 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, - 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, - 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, - 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, - 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, - 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e -]); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/framer.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/framer.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/framer.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/framer.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,335 +0,0 @@ -var framer = exports; - -var spdy = require('../../../spdy'), - Buffer = require('buffer').Buffer, - protocol = require('./'); - -// -// ### function Framer (deflate, inflate) -// #### @deflate {zlib.Deflate} Deflate stream -// #### @inflate {zlib.Inflate} Inflate stream -// Framer constructor -// -function Framer(deflate, inflate) { - this.version = 3; - this.deflate = deflate; - this.inflate = inflate; -} -exports.Framer = Framer; - -// -// ### function execute (header, body, callback) -// #### @header {Object} Frame headers -// #### @body {Buffer} Frame's body -// #### @callback {Function} Continuation callback -// Parse frame (decompress data and create streams) -// -Framer.prototype.execute = function execute(header, body, callback) { - // SYN_STREAM or SYN_REPLY - if (header.type === 0x01 || header.type === 0x02) { - var frame = protocol.parseSynHead(header.type, header.flags, body); - - body = body.slice(frame._offset); - - this.inflate(body, function(err, chunks, length) { - if (err) return callback(err); - - var pairs = new Buffer(length); - for (var i = 0, offset = 0; i < chunks.length; i++) { - chunks[i].copy(pairs, offset); - offset += chunks[i].length; - } - - frame.headers = protocol.parseHeaders(pairs); - frame.url = frame.headers.path || ''; - - callback(null, frame); - }); - // RST_STREAM - } else if (header.type === 0x03) { - callback(null, protocol.parseRst(body)); - // SETTINGS - } else if (header.type === 0x04) { - callback(null, protocol.parseSettings(body)); - } else if (header.type === 0x05) { - callback(null, { type: 'NOOP' }); - // PING - } else if (header.type === 0x06) { - callback(null, { type: 'PING', pingId: body }); - // GOAWAY - } else if (header.type === 0x07) { - callback(null, protocol.parseGoaway(body)); - } else if (header.type === 0x09) { - callback(null, protocol.parseWindowUpdate(body)); - } else { - callback(null, { type: 'unknown: ' + header.type, body: body }); - } -}; - -// -// internal, converts object into spdy dictionary -// -function headersToDict(headers, preprocess) { - function stringify(value) { - if (value !== undefined) { - if (Array.isArray(value)) { - return value.join('\x00'); - } else if (typeof value === 'string') { - return value; - } else { - return value.toString(); - } - } else { - return ''; - } - } - - // Lower case of all headers keys - var loweredHeaders = {}; - Object.keys(headers || {}).map(function(key) { - loweredHeaders[key.toLowerCase()] = headers[key]; - }); - - // Allow outer code to add custom headers or remove something - if (preprocess) preprocess(loweredHeaders); - - // Transform object into kv pairs - var len = 4, - pairs = Object.keys(loweredHeaders).filter(function(key) { - var lkey = key.toLowerCase(); - return lkey !== 'connection' && lkey !== 'keep-alive' && - lkey !== 'proxy-connection' && lkey !== 'transfer-encoding'; - }).map(function(key) { - var klen = Buffer.byteLength(key), - value = stringify(loweredHeaders[key]), - vlen = Buffer.byteLength(value); - - len += 8 + klen + vlen; - return [klen, key, vlen, value]; - }), - result = new Buffer(len); - - result.writeUInt32BE(pairs.length, 0, true); - - var offset = 4; - pairs.forEach(function(pair) { - // Write key length - result.writeUInt32BE(pair[0], offset, true); - // Write key - result.write(pair[1], offset + 4); - - offset += pair[0] + 4; - - // Write value length - result.writeUInt32BE(pair[2], offset, true); - // Write value - result.write(pair[3], offset + 4); - - offset += pair[2] + 4; - }); - - return result; -}; - -Framer.prototype._synFrame = function _synFrame(type, id, assoc, priority, dict, - callback) { - // Compress headers - this.deflate(dict, function (err, chunks, size) { - if (err) return callback(err); - - var offset = type === 'SYN_STREAM' ? 18 : 12, - total = (type === 'SYN_STREAM' ? 10 : 4) + size, - frame = new Buffer(offset + size);; - - frame.writeUInt16BE(0x8003, 0, true); // Control + Version - frame.writeUInt16BE(type === 'SYN_STREAM' ? 1 : 2, 2, true); // type - frame.writeUInt32BE(total & 0x00ffffff, 4, true); // No flag support - frame.writeUInt32BE(id & 0x7fffffff, 8, true); // Stream-ID - - if (type === 'SYN_STREAM') { - frame[4] = 2; - frame.writeUInt32BE(assoc & 0x7fffffff, 12, true); // Stream-ID - } - - frame.writeUInt8(priority & 0x7, 16, true); // Priority - - for (var i = 0; i < chunks.length; i++) { - chunks[i].copy(frame, offset); - offset += chunks[i].length; - } - - callback(null, frame); - }); -}; - -// -// ### function replyFrame (id, code, reason, headers, callback) -// #### @id {Number} Stream ID -// #### @code {Number} HTTP Status Code -// #### @reason {String} (optional) -// #### @headers {Object|Array} (optional) HTTP headers -// #### @callback {Function} Continuation function -// Sends SYN_REPLY frame -// -Framer.prototype.replyFrame = function replyFrame(id, code, reason, headers, - callback) { - var dict = headersToDict(headers, function(headers) { - headers[':status'] = code + ' ' + reason; - headers[':version'] = 'HTTP/1.1'; - }); - - this._synFrame('SYN_REPLY', id, null, 0, dict, callback); -}; - -// -// ### function streamFrame (id, assoc, headers, callback) -// #### @id {Number} stream id -// #### @assoc {Number} associated stream id -// #### @meta {Object} meta headers ( method, scheme, url, version ) -// #### @headers {Object} stream headers -// #### @callback {Function} continuation callback -// Create SYN_STREAM frame -// (needed for server push and testing) -// -Framer.prototype.streamFrame = function streamFrame(id, assoc, meta, headers, - callback) { - var dict = headersToDict(headers, function(headers) { - headers[':status'] = 200; - headers[':version'] = meta.version || 'HTTP/1.1'; - headers[':path'] = meta.path; - headers[':scheme'] = meta.scheme || 'https'; - headers[':host'] = meta.host; - }); - - this._synFrame('SYN_STREAM', id, assoc, meta.priority, dict, callback); -}; - -// -// ### function dataFrame (id, fin, data) -// #### @id {Number} Stream id -// #### @fin {Bool} Is this data frame last frame -// #### @data {Buffer} Response data -// Sends DATA frame -// -Framer.prototype.dataFrame = function dataFrame(id, fin, data) { - if (!fin && !data.length) return []; - - var frame = new Buffer(8 + data.length); - - frame.writeUInt32BE(id & 0x7fffffff, 0, true); - frame.writeUInt32BE(data.length & 0x00ffffff, 4, true); - frame.writeUInt8(fin ? 0x01 : 0x0, 4, true); - - if (data.length) data.copy(frame, 8); - - return frame; -}; - -// -// ### function pingFrame (id) -// #### @id {Buffer} Ping ID -// Sends PING frame -// -Framer.prototype.pingFrame = function pingFrame(id) { - var header = new Buffer(12); - - header.writeUInt32BE(0x80030006, 0, true); // Version and type - header.writeUInt32BE(0x00000004, 4, true); // Length - id.copy(header, 8, 0, 4); // ID - - return header; -}; - -// -// ### function rstFrame (id, code) -// #### @id {Number} Stream ID -// #### @code {NUmber} RST Code -// Sends PING frame -// -Framer.prototype.rstFrame = function rstFrame(id, code) { - var header; - - if (!(header = Framer.rstCache[code])) { - header = new Buffer(16); - - header.writeUInt32BE(0x80030003, 0, true); // Version and type - header.writeUInt32BE(0x00000008, 4, true); // Length - header.writeUInt32BE(id & 0x7fffffff, 8, true); // Stream ID - header.writeUInt32BE(code, 12, true); // Status Code - - Framer.rstCache[code] = header; - } - - return header; -}; -Framer.rstCache = {}; - -// -// ### function settingsFrame (options) -// #### @options {Object} settings frame options -// Sends SETTINGS frame with MAX_CONCURRENT_STREAMS and initial window -// -Framer.prototype.settingsFrame = function settingsFrame(options) { - var settings, - key = options.maxStreams + ':' + options.windowSize; - - if (!(settings = Framer.settingsCache[key])) { - settings = new Buffer(28); - - settings.writeUInt32BE(0x80030004, 0, true); // Version and type - settings.writeUInt32BE((4 + 8 * 2) & 0x00FFFFFF, 4, true); // length - settings.writeUInt32BE(0x00000002, 8, true); // Count of entries - - settings.writeUInt32BE(0x01000004, 12, true); // Entry ID and Persist flag - settings.writeUInt32BE(options.maxStreams & 0x7fffffff, 16, true); - - settings.writeUInt32BE(0x01000007, 20, true); // Entry ID and Persist flag - settings.writeUInt32BE(options.windowSize & 0x7fffffff, 24, true); - - Framer.settingsCache[key] = settings; - } - - return settings; -}; -Framer.settingsCache = {}; - -// -// ### function windowSizeFrame (size) -// #### @size {Number} data transfer window size -// Sends SETTINGS frame with window size -// -Framer.prototype.windowSizeFrame = function windowSizeFrame(size) { - var settings; - - if (!(settings = Framer.windowSizeCache[size])) { - settings = new Buffer(20); - - settings.writeUInt32BE(0x80030004, 0, true); // Version and type - settings.writeUInt32BE((4 + 8) & 0x00FFFFFF, 4, true); // length - settings.writeUInt32BE(0x00000001, 8, true); // Count of entries - - settings.writeUInt32BE(0x01000007, 12, true); // Entry ID and Persist flag - settings.writeUInt32BE(size & 0x7fffffff, 16, true); // Window Size (KB) - - Framer.windowSizeCache[size] = settings; - } - - return settings; -}; -Framer.windowSizeCache = {}; - -// -// ### function windowUpdateFrame (id) -// #### @id {Buffer} WindowUpdate ID -// Sends WINDOW_UPDATE frame -// -Framer.prototype.windowUpdateFrame = function windowUpdateFrame(id, delta) { - var header = new Buffer(16); - - header.writeUInt32BE(0x80030009, 0, true); // Version and type - header.writeUInt32BE(0x00000008, 4, true); // Length - header.writeUInt32BE(id & 0x7fffffff, 8, true); // ID - header.writeUInt32BE(delta & 0x7fffffff, 12, true); // delta - - return header; -}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/index.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/index.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/index.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/index.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -var v3; - -try { - v3 = require('./protocol.node'); -} catch (e) { - v3 = require('./protocol.js'); -} -module.exports = v3; - -v3.Framer = require('./framer').Framer; - -v3.dictionary = require('./dictionary').dictionary; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/protocol.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/protocol.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/protocol.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/protocol/v3/protocol.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -var protocol = exports; - -// -// ### function parseSynHead (type, flags, data) -// #### @type {Number} Frame type -// #### @flags {Number} Frame flags -// #### @data {Buffer} input data -// Returns parsed syn_* frame's head -// -protocol.parseSynHead = function parseSynHead(type, flags, data) { - var stream = type === 0x01; - - return { - type: stream ? 'SYN_STREAM' : 'SYN_REPLY', - id: data.readUInt32BE(0, true) & 0x7fffffff, - version: 3, - associated: stream ? data.readUInt32BE(4, true) & 0x7fffffff : 0, - priority: stream ? data[8] >> 5 : 0, - fin: (flags & 0x01) === 0x01, - unidir: (flags & 0x02) === 0x02, - _offset: stream ? 10 : 4 - }; -}; - -// -// ### function parseHeaders (pairs) -// #### @pairs {Buffer} header pairs -// Returns hashmap of parsed headers -// -protocol.parseHeaders = function parseHeaders(pairs) { - var count = pairs.readUInt32BE(0, true), - headers = {}; - - pairs = pairs.slice(4); - - function readString() { - var len = pairs.readUInt32BE(0, true), - value = pairs.slice(4, 4 + len); - - pairs = pairs.slice(4 + len); - - return value.toString(); - } - - while(count > 0) { - headers[readString().replace(/^:/, '')] = readString(); - count--; - } - - return headers; -}; - -// -// ### function parsesRst frame -protocol.parseRst = function parseRst(data) { - return { - type: 'RST_STREAM', - id: data.readUInt32BE(0, true) & 0x7fffffff, - status: data.readUInt32BE(4, true) - }; -}; - -protocol.parseSettings = function parseSettings(data) { - var settings = {}, - number = data.readUInt32BE(0, true), - idMap = { - 1: 'upload_bandwidth', - 2: 'download_bandwidth', - 3: 'round_trip_time', - 4: 'max_concurrent_streams', - 5: 'current_cwnd', - 6: 'download_retrans_rate', - 7: 'initial_window_size', - 8: 'client_certificate_vector_size' - }; - - for (var i=0; i options.maxStreams) { - stream.once('error', function onerror() {}); - // REFUSED_STREAM - stream._rstCode = 3; - stream.destroy(true); - } else { - self.emit('stream', stream); - - stream._init(); - } - } else { - if (frame.id) { - // Load created one - stream = self.streams[frame.id]; - - // Fail if not found - if (stream === undefined) { - if (frame.type === 'RST_STREAM') return; - self.write(self._framer.rstFrame(frame.id, 2)); - return; - } - } - - // Emit 'data' event - if (frame.type === 'DATA') { - if (frame.data.length > 0){ - if (stream._closedBy.client) { - stream._rstCode = 2; - stream.emit('error', 'Writing to half-closed stream'); - } else { - stream._recv(frame.data); - } - } - // Destroy stream if we was asked to do this - } else if (frame.type === 'RST_STREAM') { - stream._rstCode = 0; - if (frame.status === 5) { - // If client "cancels" connection - close stream and - // all associated push streams without error - stream.pushes.forEach(function(stream) { - stream.close(); - }); - stream.close(); - } else { - // Emit error on destroy - stream.destroy(new Error('Received rst: ' + frame.status)); - } - // Respond with same PING - } else if (frame.type === 'PING') { - self.write(self._framer.pingFrame(frame.pingId)); - } else if (frame.type === 'SETTINGS') { - self._setDefaultWindow(frame.settings); - } else if (frame.type === 'GOAWAY') { - self._goaway = frame.lastId; - } else if (frame.type === 'WINDOW_UPDATE') { - stream._drainSink(frame.delta); - } else { - console.error('Unknown type: ', frame.type); - } - } - - // Handle half-closed - if (frame.fin) { - // Don't allow to close stream twice - if (stream._closedBy.client) { - stream._rstCode = 2; - stream.emit('error', 'Already half-closed'); - } else { - stream._closedBy.client = true; - - // Emulate last chunked fragment - if (stream._forceChunked) { - stream._recv(last_frag, true); - } - - stream._handleClose(); - } - } - }); - - this.parser.on('version', function onversion(version) { - if (!pair) { - pair = pool.get('spdy/' + version); - self._deflate = pair.deflate; - self._inflate = pair.inflate; - } - }); - - this.parser.on('framer', function onframer(framer) { - // Generate custom settings frame and send - self.write(framer.settingsFrame(options)); - }); - - // Propagate parser errors - this.parser.on('error', function onParserError(err) { - self.emit('error', err); - }); - - socket.pipe(this.parser); - - // 2 minutes socket timeout - socket.setTimeout(2 * 60 * 1000); - socket.once('timeout', function ontimeout() { - socket.destroy(); - }); - - // Allow high-level api to catch socket errors - socket.on('error', function onSocketError(e) { - self.emit('error', e); - }); - - socket.once('close', function onclose() { - self._closed = true; - if (pair) pool.put(pair); - }); - - if (legacy) { - socket.on('drain', function ondrain() { - self.emit('drain'); - }); - } -} -util.inherits(Connection, process.EventEmitter); -exports.Connection = Connection; - -// -// ### function write (data, encoding) -// #### @data {String|Buffer} data -// #### @encoding {String} (optional) encoding -// Writes data to socket -// -Connection.prototype.write = function write(data, encoding) { - if (this.socket.writable) { - return this.socket.write(data, encoding); - } -}; - -// -// ### function _setDefaultWindow (settings) -// #### @settings {Object} -// Update the default transfer window -- in the connection and in the -// active streams -// -Connection.prototype._setDefaultWindow = function _setDefaultWindow(settings) { - if (!settings) return; - if (!settings.initial_window_size || - settings.initial_window_size.persisted) { - return; - } - - this.sinkSize = settings.initial_window_size.value; - - Object.keys(this.streams).forEach(function(id) { - this.streams[id]._updateSinkSize(settings.initial_window_size.value); - }, this); -}; - -// -// ### function Stream (connection, frame) -// #### @connection {Connection} SPDY Connection -// #### @frame {Object} SYN_STREAM data -// Abstract stream @constructor -// -function Stream(connection, frame) { - DuplexStream.call(this); - - this.connection = connection; - this.socket = connection.socket; - this.encrypted = connection.encrypted; - this._framer = connection._framer; - this._initialized = false; - - // Should chunked encoding be forced - this._forceChunked = false; - - this.ondata = this.onend = null; - - // RST_STREAM code if any - this._rstCode = 1; - this._destroyed = false; - - this._closedBy = { - client: false, - server: false - }; - - // Lock data - this._locked = false; - this._lockBuffer = []; - - // Store id - this.id = frame.id; - this.version = frame.version; - - // Store priority - this.priority = frame.priority; - - // Array of push streams associated to that one - this.pushes = []; - - // How much data can be sent TO client before next WINDOW_UPDATE - this._sinkSize = connection.sinkSize; - this._initialSinkSize = connection.sinkSize; - - // When data needs to be send, but window is too small for it - it'll be - // queued in this buffer - this._sinkBuffer = []; - - // How much data can be sent BY client before next WINDOW_UPDATE - this._initialWindowSize = connection.windowSize; - this._windowSize = connection.windowSize; - - // Create compression streams - this._deflate = connection._deflate; - this._inflate = connection._inflate; - - // Store headers - this.headers = frame.headers; - this.url = frame.url; - - this._frame = frame; - - if (legacy) { - this.readable = this.writable = true; - } - - // Call .onend() - this.once('end', function() { - var self = this; - process.nextTick(function() { - if (self.onend) self.onend(); - }); - }); - - // Handle half-close - this.once('finish', function() { - this._writeData(true, []); - this._closedBy.server = true; - if (this._sinkBuffer.length !== 0) return; - this._handleClose(); - }); -}; -util.inherits(Stream, DuplexStream); -exports.Stream = Stream; - -if (legacy) { - Stream.prototype.pause = function pause() {}; - Stream.prototype.resume = function resume() {}; -} - -// -// ### function _isGoaway () -// Returns true if any writes to that stream should be ignored -// -Stream.prototype._isGoaway = function _isGoaway() { - return this.connection._goaway && this.id > this.connection._goaway; -}; + // Instantiate http server if `ssl: false` + if (!base && options && options.plain && options.ssl === false) + return exports.create(require('http').Server, options, requestListener); -// -// ### function init () -// Initialize stream, internal -// -Stream.prototype._init = function init() { - var headers = this.headers, - req = [headers.method + ' ' + this.url + ' ' + headers.version]; - - Object.keys(headers).forEach(function (key) { - if (key !== 'method' && key !== 'url' && key !== 'version' && - key !== 'scheme') { - req.push(key + ': ' + headers[key]); - } - }); - - // Force chunked encoding - if (!headers['content-length'] && !headers['transfer-encoding']) { - req.push('Transfer-Encoding: chunked'); - this._forceChunked = true; - } - - // Add '\r\n\r\n' - req.push('', ''); - - req = new Buffer(req.join('\r\n')); - - this._recv(req, true); - this._initialized = true; -}; - -// -// ### function lock (callback) -// #### @callback {Function} continuation callback -// Acquire lock -// -Stream.prototype._lock = function lock(callback) { - if (!callback) return; - - if (this._locked) { - this._lockBuffer.push(callback); - } else { - this._locked = true; - callback.call(this, null); - } -}; - -// -// ### function unlock () -// Release lock and call all buffered callbacks -// -Stream.prototype._unlock = function unlock() { - if (this._locked) { - this._locked = false; - this._lock(this._lockBuffer.shift()); - } -}; - -// -// ### function setTimeout () -// TODO: use timers.enroll, timers.active, timers.unenroll -// -Stream.prototype.setTimeout = function setTimeout(time) {}; - -// -// ### function _handleClose () -// Close stream if it was closed by both server and client -// -Stream.prototype._handleClose = function _handleClose() { - if (this._closedBy.client && this._closedBy.server) { - this.close(); - } -}; - -// -// ### function close () -// Destroys stream -// -Stream.prototype.close = function close() { - this.destroy(); -}; - -// -// ### function destroy (error) -// #### @error {Error} (optional) error -// Destroys stream -// -Stream.prototype.destroy = function destroy(error) { - if (this._destroyed) return; - this._destroyed = true; - - delete this.connection.streams[this.id]; - if (this.id % 2 === 1) { - this.connection.streamsCount--; - } - - // If stream is not finished, RST frame should be sent to notify client - // about sudden stream termination. - if (error || !this._closedBy.server) { - // REFUSED_STREAM if terminated before 'finish' event - if (!this._closedBy.server) this._rstCode = 3; - - if (this._rstCode) { - this._lock(function() { - this.connection.scheduler.schedule( - this, - this._framer.rstFrame(this.id, this._rstCode)); - this.connection.scheduler.tick(); - - this._unlock(); - }); - } - } - - if (legacy) { - this.emit('end'); - } else { - this.push(null); - } - - if (error) this.emit('error', error); - - var self = this; - process.nextTick(function() { - self.emit('close', !!error); - }); -}; - -Stream.prototype.destroySoon = function destroySoon(error) { - return this.destroy(error); -}; - -Stream.prototype._drainSink = function _drainSink(size) { - var oldBuffer = this._sinkBuffer; - this._sinkBuffer = []; - - this._sinkSize += size; - - for (var i = 0; i < oldBuffer.length; i++) { - this._writeData(oldBuffer[i][0], oldBuffer[i][1], oldBuffer[i][2]); - } - - // Handle half-close - if (this._sinkBuffer.length === 0 && this._closedBy.server) { - this._handleClose(); - } - - if (legacy) this.emit('drain'); -}; - -// -// ### function _writeData (fin, buffer, cb) -// #### @fin {Boolean} -// #### @buffer {Buffer} -// #### @cb {Function} **optional** -// Internal function -// -Stream.prototype._writeData = function _writeData(fin, buffer, cb) { - if (this._framer.version === 3) { - // Window was exhausted, queue data - if (this._sinkSize <= 0) { - this._sinkBuffer.push([fin, buffer, cb]); - return false; - } - - var len = Math.min(this._sinkSize, buffer.length); - this._sinkSize -= len; - - // Only partial write is possible, queue rest for later - if (len < buffer.length) { - this._sinkBuffer.push([fin, buffer.slice(len)]); - buffer = buffer.slice(0, len); - fin = false; - } - } - - this._lock(function() { - var stream = this, - frame = this._framer.dataFrame(this.id, fin, buffer); - - stream.connection.scheduler.schedule(stream, frame); - stream.connection.scheduler.tick(); - - this._unlock(); - - if (cb) cb(); - }); - - return true; -}; - -// -// ### function write (data, encoding) -// #### @data {Buffer|String} data -// #### @encoding {String} data encoding -// Writes data to connection -// -Stream.prototype._write = function write(data, encoding, cb) { - // Do not send data to new connections after GOAWAY - if (this._isGoaway()) { - if (cb) cb(); - return false; - } - - return this._writeData(false, data, cb); -}; - -if (legacy) { - Stream.prototype.write = function write(data, encoding, cb) { - if (!Buffer.isBuffer(data)) { - return this._write(new Buffer(data, encoding), null, cb); - } else { - return this._write(data, encoding, cb); - } - }; - - // - // ### function end (data) - // #### @data {Buffer|String} (optional) data to write before ending stream - // #### @encoding {String} (optional) string encoding - // Send FIN data frame - // - Stream.prototype.end = function end(data, encoding) { - // Do not send data to new connections after GOAWAY - if (this._isGoaway()) return; - - if (data) this.write(data, encoding); - this.emit('finish'); - }; -} - -// -// ### function _recv (data) -// #### @data {Buffer} buffer to receive -// #### @chunked {Boolean} -// (internal) -// -Stream.prototype._recv = function _recv(data, chunked) { - // Update window if exhausted - if (!chunked && this._framer.version >= 3 && this._initialized) { - this._windowSize -= data.length; - - if (this._windowSize <= 0) { - var delta = this._initialWindowSize - this._windowSize; - this._windowSize += delta; - this.connection.write(this._framer.windowUpdateFrame(this.id, delta)); - } - } - - // Emulate chunked encoding - if (this._forceChunked && !chunked) { - // Zero-chunks are treated as end, do not emit them - if (data.length === 0) return; - - this._recv(new Buffer(data.length.toString(16)), true); - this._recv(crlf, true); - this._recv(data, true); - this._recv(crlf, true); - return; - } - - if (legacy) { - var self = this; - process.nextTick(function() { - self.emit('data', data); - if (self.ondata) { - self.ondata(data, 0, data.length); - } - }); - } else { - // Right now, http module expects socket to be working in streams1 mode. - if (this.ondata) { - this.ondata(data, 0, data.length); - } else { - this.push(data); - } - } -}; - -// -// ### function _read (bytes, cb) -// #### @bytes {Number} number of bytes to read -// Streams2 API -// -Stream.prototype._read = function read(bytes) { - // NOP -}; - -// -// ### function _updateSinkSize (size) -// #### @size {Integer} -// Update the internal data transfer window -// -Stream.prototype._updateSinkSize = function _updateSinkSize(size) { - var diff = size - this._initialSinkSize; - - this._initialSinkSize = size; - this._drainSink(diff); -}; - -// -// `net` compatibility layer -// (Copy pasted from lib/tls.js from node.js) -// -Stream.prototype.address = function address() { - return this.socket && this.socket.address(); + return new server(options, requestListener); }; - -Stream.prototype.__defineGetter__('remoteAddress', function remoteAddress() { - return this.socket && this.socket.remoteAddress; -}); - -Stream.prototype.__defineGetter__('remotePort', function remotePort() { - return this.socket && this.socket.remotePort; -}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/stream.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/stream.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/stream.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/stream.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,1152 @@ +var spdy = require('../spdy'); +var zlib = require('zlib'); +var utils = spdy.utils; +var assert = require('assert'); +var util = require('util'); +var stream = require('stream'); +var Buffer = require('buffer').Buffer; +var constants = spdy.protocol.constants; + +if (!/^v(0\.10|0\.8|0\.9)\./.test(process.version)) + var httpCommon = require('_http_common'); + + +// +// ### function Stream (connection, options) +// #### @connection {Connection} SPDY Connection +// #### @options {Object} Stream options +// Abstract stream @constructor +// +function Stream(connection, options) { + var self = this; + + utils.DuplexStream.call(this); + + this.connection = connection; + this.socket = connection.socket; + this.encrypted = connection.encrypted; + this.associated = null; + + // 0.10 hack + this._handle = { + readStop: function() { self._readStop() }, + readStart: function() { self._readStart() } + }; + + var state = {}; + this._spdyState = state; + state.timeout = connection.timeout; + state.timeoutTimer = null; + state.framer = connection._spdyState.framer; + state.initialized = false; + state.ending = false; + state.ended = false; + state.paused = false; + state.finishAttached = false; + state.decompress = options.decompress; + state.decompressor = null; + + // Store id + state.id = options.id; + state.associated = options.associated; + state.headers = options.headers || {}; + if (connection._spdyState.xForward !== null) + state.headers['x-forwarded-for'] = connection._spdyState.xForward; + + // Increment counters + state.isPush = !connection._spdyState.isServer && state.associated; + connection._spdyState.counters.streamCount++; + if (state.isPush) + connection._spdyState.counters.pushCount++; + + // Useful for PUSH streams + state.scheme = state.headers.scheme; + state.host = state.headers.host; + + if (state.isPush && state.headers['content-encoding']) { + var compression = state.headers['content-encoding']; + + // If compression was requested - setup decompressor + if (compression === 'gzip' || compression === 'deflate') + this._setupDecompressor(compression); + } + + // True if inside chunked write + state.chunkedWrite = false; + + // Store options + state.options = options; + state.isClient = !!options.client; + state.parseRequest = !!options.client; + + // RST_STREAM code if any + state.rstCode = constants.rst.PROTOCOL_ERROR; + state.destroyed = false; + + state.closedBy = { + them: false, + us: false + }; + + // Store priority + state.priority = options.priority; + + // How much data can be sent TO client before next WINDOW_UPDATE + state.sinkSize = connection._spdyState.initialSinkSize; + state.initialSinkSize = state.sinkSize; + + // When data needs to be send, but window is too small for it - it'll be + // queued in this buffer + state.sinkBuffer = []; + state.sinkDraining = false; + + // How much data can be sent BY client before next WINDOW_UPDATE + state.windowSize = connection._spdyState.initialWindowSize; + state.initialWindowSize = state.windowSize; + + this._init(); +}; +util.inherits(Stream, utils.DuplexStream); +exports.Stream = Stream; + +// Parser lookup methods +Stream.prototype._parserHeadersComplete = function parserHeadersComplete() { + if (this.parser) + return this.parser.onHeadersComplete || this.parser[1]; +}; + +Stream.prototype._parserBody = function parserBody() { + if (this.parser) + return this.parser.onBody || this.parser[2]; +}; + +Stream.prototype._parserMessageComplete = function parserMessageComplete() { + if (this.parser) + return this.parser.onMessageComplete || this.parser[3]; +}; + +// +// ### function init () +// Initialize stream +// +Stream.prototype._init = function init() { + var state = this._spdyState; + + this.setTimeout(); + this.ondata = this.onend = null; + + if (utils.isLegacy) + this.readable = this.writable = true; + + // Call .onend() + this.once('end', function() { + var self = this; + utils.nextTick(function() { + var onHeadersComplete = self._parserHeadersComplete(); + if (!onHeadersComplete && self.onend) + self.onend(); + }); + }); + + // Handle half-close + this.once('finish', function onfinish() { + if (state.chunkedWrite) + return this.once('_chunkDone', onfinish); + + var self = this; + this._writeData(true, [], function() { + state.closedBy.us = true; + if (state.sinkBuffer.length !== 0) + return; + if (utils.isLegacy) + self.emit('full-finish'); + self._handleClose(); + }); + }); + + if (state.isClient) { + var httpMessage; + Object.defineProperty(this, '_httpMessage', { + set: function(val) { + if (val) + this._attachToRequest(val); + httpMessage = val; + }, + get: function() { + return httpMessage; + }, + configurable: true, + enumerable: true + }); + } +}; + +Stream.prototype._readStop = function readStop() { + this._spdyState.paused = true; +}; + +Stream.prototype._readStart = function readStart() { + this._spdyState.paused = false; + + // Send window update if needed + this._read(); +}; + +if (utils.isLegacy) { + Stream.prototype.pause = function pause() { + this._readStop(); + }; + Stream.prototype.resume = function resume() { + this._readStart(); + }; +} + +// +// ### function _isGoaway () +// Returns true if any writes to that stream should be ignored +// +Stream.prototype._isGoaway = function _isGoaway() { + return this.connection._spdyState.goaway && + this._spdyState.id > this.connection._spdyState.goaway; +}; + +// +// ### function start (url, headers) +// #### @url {String} +// #### @headers {Object} +// Start stream, internal +// +Stream.prototype._start = function start(url, headers) { + var state = this._spdyState; + var headerList = []; + + // Create list of headeres + Object.keys(headers).map(function(key) { + if (key !== 'method' && + key !== 'url' && + key !== 'version' && + key !== 'scheme' && + key !== 'status' && + key !== 'path') { + headerList.push(key, headers[key]); + } + }); + + var info = { + url: url, + headers: headerList, + versionMajor: 1, + versionMinor: 1, + method: httpCommon ? httpCommon.methods.indexOf(headers.method) : + headers.method, + statusCode: false, + upgrade: headers.method === 'CONNECT' + }; + + // Write data directly to the parser callbacks + var onHeadersComplete = this._parserHeadersComplete(); + if (onHeadersComplete) { + onHeadersComplete.call(this.parser, info); + + // onHeadersComplete doesn't handle CONNECT + if (headers.method === 'CONNECT') { + // We don't need to handle a lack of listeners here, since there + // should always be a listener in server.js + var req = this.parser.incoming; + if (this.listeners('data').length) { + // 0.11+ only (assuming nobody other than the http lib has attached) + this.removeAllListeners('data'); + this.skipBodyParsing = true; + } + this.connection.emit('connect', req, req.socket); + } + } else { + this.emit('headersComplete', info); + } + + state.initialized = true; +}; + +// +// ### function attachToRequest (req) +// #### @req {ClientRequest} +// Attach to node.js' response +// +Stream.prototype._attachToRequest = function attachToRequest(res) { + var self = this; + + res.addTrailers = function addTrailers(headers) { + self.sendHeaders(headers); + }; + + this.on('headers', function(headers) { + var req = res.parser.incoming; + if (req) { + Object.keys(headers).forEach(function(key) { + req.trailers[key] = headers[key]; + }); + req.emit('trailers', headers); + } + }); +}; + +// +// ### function sendHeaders (headers) +// #### @headers {Object} +// +Stream.prototype.sendHeaders = function sendHeaders(headers) { + var self = this; + var state = this._spdyState; + + // Reset timeout + this.setTimeout(); + + var connection = this.connection; + this._lock(function() { + state.framer.headersFrame(state.id, headers, function(err, frame) { + if (err) { + self._unlock(); + return self.emit('error', err); + } + + connection.write(frame); + self._unlock(); + }); + }); +}; + +// +// ### function setTimeout (timeout, callback) +// #### @timeout {Number} +// #### @callback {Function} +// +Stream.prototype.setTimeout = function _setTimeout(timeout, callback) { + var self = this; + var state = this._spdyState; + + if (callback) + this.once('timeout', callback); + + // Keep PUSH's parent alive + if (this.associated) + this.associated.setTimeout(); + + state.timeout = timeout !== undefined ? timeout : state.timeout; + + if (state.timeoutTimer) { + clearTimeout(state.timeoutTimer); + state.timeoutTimer = null; + } + + if (!state.timeout) + return; + + state.timeoutTimer = setTimeout(function() { + self.emit('timeout'); + }, state.timeout); +}; + +// +// ### function _handleClose () +// Close stream if it was closed by both server and client +// +Stream.prototype._handleClose = function _handleClose() { + var state = this._spdyState; + if (state.closedBy.them && state.closedBy.us) + this.close(); +}; + +// +// ### function close () +// Destroys stream +// +Stream.prototype.close = function close() { + this.destroy(); +}; + +// +// ### function destroy (error) +// #### @error {Error} (optional) error +// Destroys stream +// +Stream.prototype.destroy = function destroy(error) { + var state = this._spdyState; + if (state.destroyed) + return; + state.destroyed = true; + + // Reset timeout + this.setTimeout(0); + + // Decrement counters + this.connection._spdyState.counters.streamCount--; + if (state.isPush) + this.connection._spdyState.counters.pushCount--; + + // Just for http.js in v0.10 + this.writable = false; + this.connection._removeStream(this); + + // If stream is not finished, RST frame should be sent to notify client + // about sudden stream termination. + if (error || !state.closedBy.us) { + if (!state.closedBy.us) + // CANCEL + if (state.isClient) + state.rstCode = constants.rst.CANCEL; + // REFUSED_STREAM if terminated before 'finish' event + else + state.rstCode = constants.rst.REFUSED_STREAM; + + if (state.rstCode) { + var self = this; + state.framer.rstFrame(state.id, + state.rstCode, + null, + function(err, frame) { + if (err) + return self.emit('error', err); + var scheduler = self.connection._spdyState.scheduler; + + scheduler.scheduleLast(self, frame); + scheduler.tick(); + }); + } + } + + var self = this; + this._recvEnd(function() { + if (error) + self.emit('error', error); + + utils.nextTick(function() { + self.emit('close', !!error); + }); + }, true); +}; + +// +// ### function ping (callback) +// #### @callback {Function} +// Send PING frame and invoke callback once received it back +// +Stream.prototype.ping = function ping(callback) { + return this.connection.ping(callback); +}; + +// +// ### function destroySoon () +// +Stream.prototype.destroySoon = function destroySoon() { + var self = this; + var state = this._spdyState; + + // Hack for http.js, when running in client mode + this.writable = false; + + // Already closed - just ignore + if (state.closedBy.us) + return; + + // Reset timeout + this.setTimeout(); + this.end(); +}; + +// +// ### function drainSink (size) +// #### @size {Number} +// Change sink size +// +Stream.prototype._drainSink = function drainSink(size) { + var state = this._spdyState; + var oldBuffer = state.sinkBuffer; + + state.sinkBuffer = []; + state.sinkSize += size; + state.sinkDraining = true; + + for (var i = 0; i < oldBuffer.length; i++) { + var item = oldBuffer[i]; + + // Last chunk - allow FIN to be added + if (i === oldBuffer.length - 1) + state.sinkDraining = false; + this._writeData(item.fin, item.buffer, item.cb, item.chunked); + } + + // Handle half-close + if (state.sinkBuffer.length === 0 && state.closedBy.us) + this._handleClose(); + + if (utils.isLegacy) + this.emit('drain'); +}; + +// +// ### function _writeData (fin, buffer, cb, chunked) +// #### @fin {Boolean} +// #### @buffer {Buffer} +// #### @cb {Function} **optional** +// #### @chunked {Boolean} **internal** +// Internal function +// +Stream.prototype._writeData = function _writeData(fin, buffer, cb, chunked) { + // If client is gone - notify caller about it + if (!this.connection.socket || !this.connection.socket.writable) + return false; + + var state = this._spdyState; + if (!state.framer.version) { + var self = this; + state.framer.on('version', function() { + self._writeData(fin, buffer, cb, chunked); + if (utils.isLegacy) + self.emit('drain'); + }); + return false; + } + + // Already closed + if (state.closedBy.us) { + this.emit('error', new Error('Write after end!')); + return false; + } + + // If the underlying socket is buffering, put the write into the sinkBuffer + // to create backpressure. + if (this.connection._spdyState.socketBuffering) { + state.sinkBuffer.push({ + fin: fin, + buffer: buffer, + cb: cb, + chunked: chunked + }); + return false; + } + + if (state.framer.version >= 3) { + // Window was exhausted, queue data + if (state.sinkSize <= 0 || + (state.framer.version >= 3.1 && + this.connection._spdyState.sinkSize <= 0)) { + state.sinkBuffer.push({ + fin: fin, + buffer: buffer, + cb: cb, + chunked: chunked + }); + return false; + } + } + if (state.chunkedWrite && !chunked) { + var self = this; + function attach() { + self.once('_chunkDone', function() { + if (state.chunkedWrite) + return attach(); + self._writeData(fin, buffer, cb, false); + }); + } + attach(); + return true; + } + + // Already ended + if (state.ended && !chunked) + return false; + + // Ending, add FIN if not set + if (!fin && !chunked && state.ending) { + if (utils.isLegacy) + fin = this.listeners('_chunkDone').length === 0; + else + fin = this._writableState.length === 0; + fin = fin && false && state.sinkBuffer.length === 0 && !state.sinkDraining; + } + if (!chunked && fin) + state.ended = true; + + var maxChunk = this.connection._spdyState.maxChunk; + // Slice buffer into parts with size <= `maxChunk` + if (maxChunk && maxChunk < buffer.length) { + var preend = buffer.length - maxChunk; + var chunks = []; + for (var i = 0; i < preend; i += maxChunk) + chunks.push(buffer.slice(i, i + maxChunk)); + + // Last chunk + chunks.push(buffer.slice(i)); + + var self = this; + function send(err) { + function done(err) { + state.chunkedWrite = false; + self.emit('_chunkDone'); + if (cb) + cb(err); + } + + if (err) + return done(err); + + var chunk = chunks.shift(); + if (chunks.length === 0) { + self._writeData(fin, chunk, function(err) { + // Ensure that `finish` listener will catch this + done(err); + }, true); + } else { + self._writeData(false, chunk, send, true); + } + } + + state.chunkedWrite = true; + send(); + return true; + } + + if (state.framer.version >= 3) { + var len = Math.min(state.sinkSize, buffer.length); + if (state.framer.version >= 3.1) + len = Math.min(this.connection._spdyState.sinkSize, len); + this.connection._spdyState.sinkSize -= len; + state.sinkSize -= len; + + // Only partial write is possible, queue rest for later + if (len < buffer.length) { + state.sinkBuffer.push({ + fin: fin, + buffer: buffer.slice(len), + cb: cb, + chunked: chunked + }); + buffer = buffer.slice(0, len); + fin = false; + cb = null; + } + } + + // Reset timeout + this.setTimeout(); + + this._lock(function() { + var stream = this; + + state.framer.dataFrame(state.id, fin, buffer, function(err, frame) { + if (err) { + stream._unlock(); + return stream.emit('error', err); + } + + var scheduler = stream.connection._spdyState.scheduler; + scheduler.schedule(stream, frame); + scheduler.tick(cb); + + stream._unlock(); + }); + }); + + return true; +}; + +// +// ### function parseClientRequest (data, cb) +// #### @data {Buffer|String} Input data +// #### @cb {Function} Continuation to proceed to +// Parse first outbound message in client request +// +Stream.prototype._parseClientRequest = function parseClientRequest(data, cb) { + var state = this._spdyState; + + state.parseRequest = false; + + var lines = data.toString().split(/\r\n\r\n/); + var body = data.slice(Buffer.byteLength(lines[0]) + 4); + lines = lines[0].split(/\r\n/g); + var status = lines[0].match(/^([a-z]+)\s([^\s]+)\s(.*)$/i); + var headers = {}; + + assert(status !== null); + var method = status[1].toUpperCase(); + var url = status[2]; + var version = status[3].toUpperCase(); + var host = ''; + + // Transform headers and determine host + lines.slice(1).forEach(function(line) { + // Last line + if (!line) + return; + + // Normal line - `Key: Value` + var match = line.match(/^(.*?):\s*(.*)$/); + assert(match !== null); + + var key = match[1].toLowerCase(); + var value = match[2]; + + if (key === 'host') + host = value; + else if (key !== 'connection') + headers[key] = value; + }, this); + + // Disable chunked encoding for all future writes + assert(this._httpMessage); + var chunkedEncoding = this._httpMessage.chunkedEncoding; + this._httpMessage.chunkedEncoding = false; + + // Reset timeout + this.setTimeout(); + + var self = this; + var connection = this.connection; + this._lock(function() { + state.framer.streamFrame(state.id, 0, { + method: method, + host: host, + url: url, + version: version, + priority: self.priority + }, headers, function(err, frame) { + if (err) { + self._unlock(); + return self.emit('error', err); + } + connection.write(frame); + self._unlock(); + connection._addStream(self); + + self.emit('_spdyRequest'); + state.initialized = true; + if (cb) + cb(); + }) + }); + + // Yeah, node.js gave us a body with the request + if (body) { + if (chunkedEncoding) { + var i = 0; + while (i < body.length) { + var lenStart = i; + + // Skip length and \r\n + for (; i + 1 < body.length; i++) + if (body[i] === 0xd && body[i + 1] === 0xa) + break; + if (i === body.length - 1) + return self.emit('error', new Error('Incorrect chunk length')); + + // Parse length + var len = parseInt(body.slice(lenStart, i).toString(), 16); + + // Get body chunk + if (i + 2 + len >= body.length) + return self.emit('error', new Error('Chunk length OOB')); + + // Ignore empty chunks + if (len !== 0) { + var chunk = body.slice(i + 2, i + 2 + len); + this._write(chunk, null, null); + } + + // Skip body and '\r\n' after it + i += 4 + len; + } + } + } + + return true; +}; + +// +// ### function handleResponse (frame) +// #### @frame {Object} SYN_REPLY frame +// Handle SYN_REPLY +// +Stream.prototype._handleResponse = function handleResponse(frame) { + var state = this._spdyState; + assert(state.isClient); + + var headers = frame.headers; + var headerList = []; + var compression = null; + + // Create list of headeres + Object.keys(headers).map(function(key) { + var val = headers[key]; + + if (state.decompress && + key === 'content-encoding' && + (val === 'gzip' || val === 'deflate')) + compression = val; + else if (key !== 'status' && key !== 'version') + headerList.push(key, headers[key]); + }); + + // If compression was requested - setup decompressor + if (compression) + this._setupDecompressor(compression); + + var isConnectRequest = this._httpMessage && + this._httpMessage.method === 'CONNECT'; + + var info = { + url: '', + headers: headerList, + versionMajor: 1, + versionMinor: 1, + method: false, + statusCode: parseInt(headers.status, 10), + statusMessage: headers.status.split(/ /)[1], + upgrade: isConnectRequest + }; + + // Write data directly to the parser callbacks + var onHeadersComplete = this._parserHeadersComplete(); + if (onHeadersComplete) { + onHeadersComplete.call(this.parser, info); + + // onHeadersComplete doesn't handle CONNECT + if (isConnectRequest) { + var req = this._httpMessage; + var res = this.parser.incoming; + req.res = res; + if (this.listeners('data').length) { + // 0.11+ only (assuming nobody other than the http lib has attached) + this.removeAllListeners('data'); + this.skipBodyParsing = true; + } + if (this._httpMessage.listeners('connect').length > 0) + this._httpMessage.emit('connect', res, res.socket); + else + this.destroy(); + } + } else { + this.emit('headersComplete', info); + } + + state.initialized = true; +}; + +// +// ### function setupDecompressor (type) +// #### @type {String} 'gzip' or 'deflate' +// Setup decompressor +// +Stream.prototype._setupDecompressor = function setupDecompressor(type) { + var self = this; + var state = this._spdyState; + var options = { flush: zlib.Z_SYNC_FLUSH }; + + if (state.decompressor !== null) + return this.emit('error', new Error('Decompressor already created')); + + state.decompressor = type === 'gzip' ? zlib.createGunzip(options) : + zlib.createInflate(options); + if (spdy.utils.isLegacy) + state.decompressor._flush = options.flush; + state.decompressor.on('data', function(chunk) { + self._recv(chunk, true); + }); + state.decompressor.on('error', function(err) { + self.emit('error', err); + }); +} + +// +// ### function decompress(data) +// #### @data {Buffer} Input data +// Decompress input data and call `._recv(result, true)` +// +Stream.prototype._decompress = function decompress(data) { + var state = this._spdyState; + + // Put data in + state.decompressor.write(data); +}; + +// +// ### function write (data, encoding) +// #### @data {Buffer|String} data +// #### @encoding {String} data encoding +// Writes data to connection +// +Stream.prototype._write = function write(data, encoding, cb) { + var r = true; + var state = this._spdyState; + + // Ignore all outgoing data for PUSH streams, they're unidirectional + if (state.isClient && state.associated) { + cb(); + return r; + } + + // First write is a client request + if (state.parseRequest) { + this._parseClientRequest(data, cb); + } else { + // No chunked encoding is allowed at this point + assert(!this._httpMessage || !this._httpMessage.chunkedEncoding); + + // Do not send data to new connections after GOAWAY + if (this._isGoaway()) { + if (cb) + cb(); + r = false; + } else { + r = this._writeData(false, data, cb); + } + } + + if (this._httpMessage && state.isClient && !state.finishAttached) { + state.finishAttached = true; + var self = this; + + // If client request was ended - send FIN data frame + this._httpMessage.once('finish', function() { + if (self._httpMessage.output && + !self._httpMessage.output.length && + self._httpMessage.method !== 'CONNECT') + self.end(); + }); + } + + return r; +}; + +if (spdy.utils.isLegacy) { + Stream.prototype.write = function write(data, encoding, cb) { + if (typeof encoding === 'function' && !cb) { + cb = encoding; + encoding = null; + } + if (!Buffer.isBuffer(data)) + return this._write(new Buffer(data, encoding), null, cb); + else + return this._write(data, encoding, cb); + }; + + // + // ### function end (data, encoding, cb) + // #### @data {Buffer|String} (optional) data to write before ending stream + // #### @encoding {String} (optional) string encoding + // #### @cb {Function} + // Send FIN data frame + // + Stream.prototype.end = function end(data, encoding, cb) { + // Do not send data to new connections after GOAWAY + if (this._isGoaway()) + return; + + this._spdyState.ending = true; + + if (data) + this.write(data, encoding, cb); + this.emit('finish'); + }; +} else { + + // + // ### function end (data, encoding, cb) + // #### @data {Buffer|String} (optional) data to write before ending stream + // #### @encoding {String} (optional) string encoding + // #### @cb {Function} + // Send FIN data frame + // + Stream.prototype.end = function end(data, encoding, cb) { + this._spdyState.ending = true; + + Stream.super_.prototype.end.call(this, data, encoding, cb); + }; +} + +// +// ### function _recv (data, decompressed) +// #### @data {Buffer} buffer to receive +// #### @decompressed {Boolean} **internal** `true` if already decompressed +// (internal) +// +Stream.prototype._recv = function _recv(data, decompressed) { + var state = this._spdyState; + + // Update window if exhausted + if (state.framer.version >= 3 && state.initialized) { + state.windowSize -= data.length; + + // If running on node.js 0.8 - don't send WINDOW_UPDATE if paused + if (spdy.utils.isLegacy && !state.paused) + this._read(); + } + + // Decompress data if needed + if (state.decompressor && !decompressed) + return this._decompress(data); + + // Reset timeout + this.setTimeout(); + + if (this.parser && !this.skipBodyParsing) { + var onBody = this._parserBody(); + if (onBody) + onBody.call(this.parser, data, 0, data.length); + } + + if (spdy.utils.isLegacy) { + var self = this; + utils.nextTick(function() { + self.emit('data', data); + if (self.ondata && !onBody) + self.ondata(data, 0, data.length); + }); + } else { + // 0.11 - 0.12 - do not emit events at all + if (!onBody || !this.parser[2]) { + // Right now, http module expects socket to be working in streams1 mode. + if (this.ondata && !onBody) + this.ondata(data, 0, data.length); + else + this.push(data); + } + } + + // Call `._read()` if high watermark isn't reached + if (!spdy.utils.isLegacy) + this.read(0); +}; + +// +// ### function _recvEnd (callback, quite) +// #### @callback {Function} +// #### @quite {Boolean} If true - do not emit any events +// Receive FIN frame +// +Stream.prototype._recvEnd = function _recvEnd(callback, quite) { + var state = this._spdyState; + + // Sync with the decompressor + if (state.decompressor) { + var self = this; + state.decompressor.write('', function() { + state.decompressor = null; + self._recvEnd(callback, quite); + }); + return; + } + if (!quite) { + var onMessageComplete = this._parserMessageComplete(); + if (onMessageComplete) + onMessageComplete.call(this.parser); + + if (spdy.utils.isLegacy) + this.emit('end'); + else + this.push(null); + } + if (callback) + callback(); +}; + +// +// ### function _read (bytes) +// #### @bytes {Number} number of bytes to read +// Streams2 API +// +Stream.prototype._read = function read(bytes) { + var state = this._spdyState; + + // Send update frame if read is requested + if (state.framer.version >= 3 && + state.initialized && + state.windowSize <= state.initialWindowSize / 2) { + var delta = state.initialWindowSize - state.windowSize; + state.windowSize += delta; + var self = this; + state.framer.windowUpdateFrame(state.id, delta, function(err, frame) { + if (err) + return self.emit('error', err); + self.connection.write(frame); + }); + } + + if (!spdy.utils.isLegacy) + this.push(''); +}; + +// +// ### function _updateSinkSize (size) +// #### @size {Integer} +// Update the internal data transfer window +// +Stream.prototype._updateSinkSize = function _updateSinkSize(size) { + var state = this._spdyState; + var delta = size - state.initialSinkSize; + + state.initialSinkSize = size; + this._drainSink(delta); +}; + +// +// ### function lock (callback) +// #### @callback {Function} continuation callback +// Acquire lock +// +Stream.prototype._lock = function lock(callback) { + if (!callback) + return; + + var self = this; + this.connection._lock(function(err) { + callback.call(self, err); + }); +}; + +// +// ### function unlock () +// Release lock and call all buffered callbacks +// +Stream.prototype._unlock = function unlock() { + this.connection._unlock(); +}; + +// +// `net` compatibility layer +// (Copy pasted from lib/tls.js from node.js) +// +Stream.prototype.address = function address() { + return this.socket && this.socket.address(); +}; + +Stream.prototype.__defineGetter__('remoteAddress', function remoteAddress() { + return this.socket && this.socket.remoteAddress; +}); + +Stream.prototype.__defineGetter__('remotePort', function remotePort() { + return this.socket && this.socket.remotePort; +}); + +Stream.prototype.setNoDelay = function setNoDelay(enable) { + return this.socket && this.socket.setNoDelay(enable); +}; + +Stream.prototype.setKeepAlive = function(setting, msecs) { + return this.socket && this.socket.setKeepAlive(setting, msecs); +}; + +Stream.prototype.getPeerCertificate = function() { + return this.socket && this.socket.getPeerCertificate(); +}; + +Stream.prototype.getSession = function() { + return this.socket && this.socket.getSession(); +}; + +Stream.prototype.isSessionReused = function() { + return this.socket && this.socket.isSessionReused(); +}; + +Stream.prototype.getCipher = function() { + return this.socket && this.socket.getCipher(); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/utils.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/utils.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/utils.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/utils.js 2014-11-26 21:46:00.000000000 +0000 @@ -1,39 +1,57 @@ var spdy = require('../spdy'), utils = exports; -var zlib = require('zlib'), +var stream = require('stream'), + zlib = require('zlib'), Buffer = require('buffer').Buffer; +// Export streams related stuff +utils.isLegacy = !stream.Duplex; +if (utils.isLegacy) + utils.DuplexStream = stream; +else + utils.DuplexStream = stream.Duplex; + // -// ### function createDeflate () +// ### function createDeflate (version, compression) +// #### @version {Number} SPDY version +// #### @compression {Boolean} whether to enable compression // Creates deflate stream with SPDY dictionary // -utils.createDeflate = function createDeflate(version) { +utils.createDeflate = function createDeflate(version, compression) { var deflate = zlib.createDeflate({ - dictionary: spdy.protocol[version].dictionary, - windowBits: 11 + dictionary: spdy.protocol.dictionary[version], + flush: zlib.Z_SYNC_FLUSH, + windowBits: 11, + level: compression ? zlib.Z_DEFAULT_COMPRESSION : zlib.Z_NO_COMPRESSION }); // Define lock information early deflate.locked = false; - deflate.lockBuffer = []; + deflate.lockQueue = []; + if (spdy.utils.isLegacy) + deflate._flush = zlib.Z_SYNC_FLUSH; return deflate; }; // -// ### function createInflate () +// ### function createInflate (version) +// #### @version {Number} SPDY version // Creates inflate stream with SPDY dictionary // utils.createInflate = function createInflate(version) { var inflate = zlib.createInflate({ - dictionary: spdy.protocol[version].dictionary, + dictionary: spdy.protocol.dictionary[version], + flush: zlib.Z_SYNC_FLUSH, windowBits: 15 }); // Define lock information early inflate.locked = false; - inflate.lockBuffer = []; + inflate.lockQueue = []; + if (spdy.utils.isLegacy) + inflate._flush = zlib.Z_SYNC_FLUSH; return inflate; }; @@ -45,14 +63,14 @@ // utils.resetZlibStream = function resetZlibStream(stream, callback) { if (stream.locked) { - stream.lockBuffer.push(function() { + stream.lockQueue.push(function() { resetZlibStream(stream, callback); }); return; } stream.reset(); - stream.lockBuffer = []; + stream.lockQueue = []; callback(null); }; @@ -66,12 +84,11 @@ // Compress/decompress data and pass it to callback // utils.zstream = function zstream(stream, buffer, callback) { - var flush = stream._flush, - chunks = [], + var chunks = [], total = 0; if (stream.locked) { - stream.lockBuffer.push(function() { + stream.lockQueue.push(function() { zstream(stream, buffer, callback); }); return; @@ -83,23 +100,26 @@ total += chunk.length; } stream.on('data', collect); - stream.write(buffer); - stream.once('error', function(err) { - stream.removeAllListeners('data'); - callback(err); - }); + stream.write(buffer, done); - stream.flush(function() { + function done() { stream.removeAllListeners('data'); stream.removeAllListeners('error'); - stream._flush = flush; - callback(null, chunks, total); + if (callback) + callback(null, chunks, total); stream.locked = false; - var deferred = stream.lockBuffer.shift(); - if (deferred) deferred(); + var deferred = stream.lockQueue.shift(); + if (deferred) + deferred(); + }; + + stream.once('error', function(err) { + stream.removeAllListeners('data'); + callback(err); + callback = null; }); }; @@ -113,3 +133,8 @@ utils.zstream(stream, data, callback); }; }; + +if (typeof setImmediate === 'undefined') + utils.nextTick = process.nextTick.bind(process); +else + utils.nextTick = setImmediate; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/zlib-pool.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/zlib-pool.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy/zlib-pool.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy/zlib-pool.js 2014-11-26 21:46:00.000000000 +0000 @@ -2,22 +2,26 @@ spdy = require('../spdy'); // -// ### function Pool () +// ### function Pool (compression) +// #### @compression {Boolean} whether to enable compression // Zlib streams pool // -function Pool() { +function Pool(compression) { + this.compression = compression; this.pool = { 'spdy/2': [], - 'spdy/3': [] + 'spdy/3': [], + 'spdy/3.1': [] }; } // -// ### function create () +// ### function create (compression) +// #### @compression {Boolean} whether to enable compression // Returns instance of Pool // -zlibpool.create = function create() { - return new Pool(); +zlibpool.create = function create(compression) { + return new Pool(compression); }; var x = 0; @@ -33,7 +37,7 @@ return { version: version, - deflate: spdy.utils.createDeflate(id), + deflate: spdy.utils.createDeflate(id, this.compression), inflate: spdy.utils.createInflate(id) }; } @@ -51,8 +55,7 @@ spdy.utils.resetZlibStream(pair.deflate, done); function done() { - if (--waiting === 0) { + if (--waiting === 0) self.pool[pair.version].push(pair); - } } }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/lib/spdy.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/lib/spdy.js 2014-11-26 21:46:00.000000000 +0000 @@ -4,19 +4,7 @@ spdy.utils = require('./spdy/utils'); // Export parser&framer -spdy.protocol = {}; - -try { - spdy.protocol.generic = require('./spdy/protocol/generic.node'); -} catch (e) { - spdy.protocol.generic = require('./spdy/protocol/generic.js'); -} - -// Supported SPDY versions -spdy.protocol[2] = require('./spdy/protocol/v2'); -spdy.protocol[3] = require('./spdy/protocol/v3'); - -spdy.parser = require('./spdy/parser'); +spdy.protocol = require('./spdy/protocol'); // Export ServerResponse spdy.response = require('./spdy/response'); @@ -27,6 +15,15 @@ // Export ZlibPool spdy.zlibpool = require('./spdy/zlib-pool'); +// Export Connection and Stream +spdy.Stream = require('./spdy/stream').Stream; +spdy.Connection = require('./spdy/connection').Connection; + // Export server spdy.server = require('./spdy/server'); +spdy.Server = spdy.server.Server; spdy.createServer = spdy.server.create; + +// Export client +spdy.Agent = require('./spdy/client').Agent; +spdy.createAgent = require('./spdy/client').create; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/package.json thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/package.json --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/package.json 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/package.json 2014-11-26 21:46:00.000000000 +0000 @@ -1,7 +1,8 @@ { "name": "spdy", - "version": "1.8.8", + "version": "1.29.1", "description": "Implementation of the SPDY protocol on node.js.", + "license": "MIT", "keywords": [ "spdy" ], diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/README.md thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/README.md --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/README.md 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/README.md 2014-11-26 21:46:00.000000000 +0000 @@ -5,10 +5,11 @@ With this module you can create [SPDY](http://www.chromium.org/spdy) servers in node.js with natural http module interface and fallback to regular https -(for browsers that doesn't support SPDY yet). +(for browsers that don't support SPDY yet). ## Usage +Server: ```javascript var spdy = require('spdy'), fs = require('fs'); @@ -16,10 +17,13 @@ var options = { key: fs.readFileSync(__dirname + '/keys/spdy-key.pem'), cert: fs.readFileSync(__dirname + '/keys/spdy-cert.pem'), - ca: fs.readFileSync(__dirname + '/keys/spdy-csr.pem'), + ca: fs.readFileSync(__dirname + '/keys/spdy-ca.pem'), - // SPDY-specific options - windowSize: 1024, // Server's window size + // **optional** SPDY-specific options + windowSize: 1024 * 1024, // Server's window size + + // **optional** if true - server will send 3.1 frames on 3.0 *plain* spdy + autoSpdy31: false }; var server = spdy.createServer(options, function(req, res) { @@ -30,6 +34,36 @@ server.listen(443); ``` +Client: +```javascript +var spdy = require('spdy'); +var http = require('http'); + +var agent = spdy.createAgent({ + host: 'www.google.com', + port: 443, + + // Optional SPDY options + spdy: { + plain: false or true, + ssl: false or true, + version: 3 // Force SPDY version + } +}); + +http.get({ + host: 'www.google.com', + agent: agent +}, function(response) { + console.log('yikes'); + // Here it goes like with any other node.js HTTP request + // ... + // And once we're done - we may close TCP connection to server + // NOTE: All non-closed requests will die! + agent.close(); +}).end(); +``` + And by popular demand - usage with [express](https://github.com/visionmedia/express): @@ -78,11 +112,12 @@ ```javascript spdy.createServer(options, function(req, res) { var headers = { 'content-type': 'application/javascript' }; - res.push('/main.js', headers, function(err, stream) { - if (err) return; - - stream.end('alert("hello from push stream!");'); + var stream = res.push('/main.js', headers); + stream.on('acknowledge', function() { + }); + stream.on('error', function() { }); + stream.end('alert("hello from push stream!");'); res.end(''); }).listen(443); @@ -100,19 +135,70 @@ (stream object have API compatible with a [net.Socket](http://nodejs.org/docs/latest/api/net.html#net.Socket) ). +Client usage: +```javascript +var agent = spdy.createAgent({ /* ... */ }); +agent.on('push', function(stream) { + stream.on('error', function(err) { + // Handle error + }); + // Read data from stream + // ... + // stream.associated points to associated client-initiated stream +}); +``` + +NOTE: You're responsible for the `stream` object once given it in `.push()` +callback. Hence ignoring `error` events on it might result in uncaught +exceptions and crash your program. + +### Trailing headers + +Server usage: +```javascript +function (req, res) { + // Send trailing headers to client + res.addTrailers({ header1: 'value1', header2: 'value2' }); + + // On client's trailing headers + req.on('trailers', function(headers) { + // ... + }); +} +``` + +Client usage: +```javascript +var req = http.request({ agent: spdyAgent, /* ... */ }).function (res) { + // On server's trailing headers + res.on('trailers', function(headers) { + // ... + }); +}); +req.write('stuff'); +req.addTrailers({ /* ... */ }); +req.end(); +``` + ### Options All options supported by [tls](http://nodejs.org/docs/latest/api/tls.html#tls.createServer) are working with node-spdy. In addition, `maxStreams` options is available. it allows you -controlling [maximum concurrent streams][http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2#TOC-SETTINGS] +controlling [maximum concurrent streams](http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2#TOC-SETTINGS) protocol option (if client will start more streams than that limit, RST_STREAM will be sent for each additional stream). Additional options: -* `plain` - if defined, server will accept only plain (non-encrypted) - connections. +* `plain` - if defined, server will ignore NPN and ALPN data and choose whether + to use spdy or plain http by looking at first data packet. +* `ssl` - if `false` and `options.plain` is `true`, `http.Server` will be used + as a `base` class for created server. +* `maxChunk` - if set and non-falsy, limits number of bytes sent in one DATA + chunk. Setting it to non-zero value is recommended if you care about + interleaving of outgoing data from multiple different streams. + (defaults to 8192) #### Contributors @@ -128,7 +214,7 @@ This software is licensed under the MIT License. -Copyright Fedor Indutny, 2012. +Copyright Fedor Indutny, 2014. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/benchmarks/syn.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/benchmarks/syn.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/benchmarks/syn.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/benchmarks/syn.js 2014-11-26 21:46:00.000000000 +0000 @@ -17,7 +17,10 @@ }); function request(port, host, data, callback) { - var socket = tls.connect(port, host, {NPNProtocols: ['spdy/2']}, function() { + var socket = tls.connect(port, host, { + NPNProtocols: ['spdy/2'], + ALPNProtocols: ['spdy/2'] + }, function() { socket.write(data); socket.once('data', function() { socket.destroy(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/connect-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/connect-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/connect-test.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/connect-test.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,205 @@ +var assert = require('assert'), + spdy = require('../../'), + zlib = require('zlib'), + keys = require('../fixtures/keys'), + https = require('https'), + tls = require('tls'), + Buffer = require('buffer').Buffer, + PORT = 8081; + +suite('A SPDY Server / Connect', function() { + var server; + var fox = 'The quick brown fox jumps over the lazy dog'; + + setup(function(done) { + server = spdy.createServer(keys, function(req, res) { + var comp = req.url === '/gzip' ? zlib.createGzip() : + req.url === '/deflate' ? zlib.createDeflate() : + null; + + // Terminate connection gracefully + if (req.url === '/goaway') + req.socket.connection.end(); + + if (!comp) + return res.end(fox); + + res.writeHead(200, { 'Content-Encoding' : req.url.slice(1) }); + comp.on('data', function(chunk) { + res.write(chunk); + }); + comp.once('end', function() { + res.end(); + }); + comp.end(fox); + }); + + server.listen(PORT, done); + }); + + teardown(function(done) { + server.close(done); + }); + + test('should respond on regular https requests', function(done) { + var req = https.request({ + host: '127.0.0.1', + port: PORT, + path: '/', + method: 'GET', + agent: false, + rejectUnauthorized: false + }, function(res) { + var received = ''; + res.on('data', function(chunk) { + received += chunk; + }); + res.once('end', function() { + assert.equal(received, fox); + done(); + }); + assert.equal(res.statusCode, 200); + }); + req.end(); + }); + + function spdyReqTest(url) { + test('should respond on spdy requests on ' + url, function(done) { + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + rejectUnauthorized: false + }); + + var req = https.request({ + path: url, + method: 'GET', + agent: agent, + }, function(res) { + var received = ''; + res.on('data', function(chunk) { + received += chunk; + }); + res.once('end', function() { + assert.equal(received, fox); + agent.close(); + done(); + }); + assert.equal(res.statusCode, 200); + }); + req.end(); + }); + } + + spdyReqTest('/'); + spdyReqTest('/gzip'); + spdyReqTest('/deflate'); + + test('should not fail at a lot of RSTs', function(done) { + var s = tls.connect({ + host: '127.0.0.1', + port: PORT, + NPNProtocols: [ 'spdy/3' ], + rejectUnauthorized: false + }, function() { + var rst = new Buffer([ + 0x80, 0x03, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00 + ]); + var rsts = []; + for (var i = 0; i < 1000; i++) + rsts.push(rst); + rsts = Buffer.concat(rsts, rst.length * rsts.length); + for (var i = 0; i < 10; i++) + s.write(rsts); + s.write(rsts, function() { + s.destroy(); + done(); + }); + }); + }); + + test('should not decompress stream when decompress is false', function(done) { + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + rejectUnauthorized: false, + spdy: { + decompress: false + } + }); + + var req = https.request({ + path: '/gzip', + method: 'GET', + agent: agent, + }, function(res) { + var received = []; + res.on('data', function(chunk) { + received.push(chunk); + }); + res.once('end', function() { + agent.close(); + + zlib.gunzip(Buffer.concat(received), function(err, decompressed) { + assert.equal(decompressed, fox); + done(); + }); + }); + assert.equal(res.statusCode, 200); + assert.equal(res.headers['content-encoding'], 'gzip'); + }); + req.end(); + }); + + test('should not create RangeErrors on client errors', function(done) { + // https://github.com/indutny/node-spdy/issues/147 + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + rejectUnauthorized: true + }).on('error', function (err) { + assert(err.message === 'self signed certificate' || + err.message === 'DEPTH_ZERO_SELF_SIGNED_CERT'); + }); + + var req = https.request({ + path: '/', + method: 'GET', + agent: agent + }); + req.on('error', function (err) { + assert.equal(err.code, 'ECONNRESET'); + done(); + }); + req.end(); + }); + + test('should not support GOAWAY', function(done) { + // https://github.com/indutny/node-spdy/issues/147 + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + rejectUnauthorized: false + }); + + var total = ''; + var req = https.request({ + path: '/goaway', + method: 'GET', + agent: agent + }, function(res) { + res.on('data', function(chunk) { + total += chunk; + }); + }); + req.end(); + + agent._spdyState.socket.once('close', function() { + assert.equal(total, fox); + done(); + }); + }); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/framer-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/framer-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/framer-test.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/framer-test.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ -var assert = require('assert'), - spdy = require('../../'), - Buffer = require('buffer').Buffer, - Stream = require('stream').Stream; - -suite('A Framer of SPDY module', function() { - var inflate, - deflate, - framer; - - setup(function() { - inflate = spdy.utils.zwrap(spdy.utils.createInflate(2)); - deflate = spdy.utils.zwrap(spdy.utils.createDeflate(2)); - framer = new spdy.protocol[2].Framer(deflate, inflate); - }); - - /* - deflate.on('data', function(b) {console.log(b)}); - deflate.write(new Buffer([ - 0x00, 0x02, // Number of name+value - 0, 0x04, // Name length - 0x68, 0x6f, 0x73, 0x74, // 'host' - 0, 0x09, // Value length - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, // 'localhost' - 0, 0x06, - 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, // 'custom', - 0, 0x1, - 0x31 // '1' - ])); - deflate.flush(); - */ - - suite('frame parsing', function() { - test('given a SYN_STREAM should return correct frame', function(done) { - var body = new Buffer([ - 0x00, 0x00, 0x00, 0x01, // Stream ID - 0x00, 0x00, 0x00, 0x00, // Associated Stream ID - 0x00, 0x00, // Priority + Unused - 0x78, 0xbb, 0xdf, 0xa2, 0x51, 0xb2, // Deflated Name/Value pairs - 0x62, 0x60, 0x62, 0x60, 0x01, 0xe5, 0x12, - 0x06, 0x4e, 0x50, 0x50, 0xe6, 0x80, 0x99, - 0x6c, 0xc9, 0xa5, 0xc5, 0x25, 0xf9, 0xb9, - 0x0c, 0x8c, 0x86, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff - ]); - framer.execute({ - control: true, - type: 1, - length: body.length - }, body, function(err, frame) { - assert.ok(!err); - assert.equal(frame.type, 'SYN_STREAM'); - assert.equal(frame.id, 1); - assert.equal(frame.associated, 0); - assert.equal(frame.headers.host, 'localhost'); - assert.equal(frame.headers.custom, '1'); - done(); - }); - }); - - test('given a SYN_REPLY should return correct frame', function(done) { - var body = new Buffer([ - 0x00, 0x00, 0x00, 0x01, // Stream ID - 0x00, 0x00, // Unused - 0x78, 0xbb, 0xdf, 0xa2, 0x51, 0xb2, // Deflated Name/Value pairs - 0x62, 0x60, 0x62, 0x60, 0x01, 0xe5, 0x12, - 0x06, 0x4e, 0x50, 0x50, 0xe6, 0x80, 0x99, - 0x6c, 0xc9, 0xa5, 0xc5, 0x25, 0xf9, 0xb9, - 0x0c, 0x8c, 0x86, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff - ]); - framer.execute({ - control: true, - type: 2, - length: body.length - }, body, function(err, frame) { - assert.ok(!err); - assert.equal(frame.type, 'SYN_REPLY'); - assert.equal(frame.id, 1); - assert.equal(frame.headers.host, 'localhost'); - assert.equal(frame.headers.custom, '1'); - done(); - }); - }); - - test('given a RST_STREAM should return correct frame', function(done) { - var body = new Buffer([0, 0, 0, 1, 0, 0, 0, 2]); - framer.execute({ - control: true, - type: 3, - length: body.length - }, body, function(err, frame) { - assert.ok(!err); - assert.equal(frame.type, 'RST_STREAM'); - assert.equal(frame.id, 1); - assert.equal(frame.status, 2); - done(); - }); - }); - - test('given a NOOP frame should return correct frame', function(done) { - framer.execute({ - control: true, - type: 5, - length: 0 - }, new Buffer(0), function(err, frame) { - assert.ok(!err); - assert.equal(frame.type, 'NOOP'); - done(); - }); - }); - - test('given a PING frame should return correct frame', function(done) { - framer.execute({ - control: true, - type: 6, - length: 0 - }, new Buffer(0), function(err, frame) { - assert.ok(!err); - assert.equal(frame.type, 'PING'); - done(); - }); - }); - - test('given a GOAWAY frame should return correct frame', function(done) { - var body = new Buffer([0, 0, 0, 1]); - framer.execute({ - control: true, - type: 7, - length: body.length - }, body, function(err, frame) { - assert.ok(!err); - assert.equal(frame.type, 'GOAWAY'); - assert.equal(frame.lastId, 1); - done(); - }); - }); - }); - - suite('frame generation', function() { - test('.replyFrame() should generate correct frame', function(done) { - framer.replyFrame(1, 200, 'ok', {}, function(err, chunks) { - assert.equal(err, null); - assert.ok(chunks.length > 1); - done(); - }); - }); - - test('.streamFrame() should generate correct frame', function(done) { - framer.streamFrame(2, 1, { url : '/' }, {}, function(err, chunks) { - assert.equal(err, null); - assert.ok(chunks.length > 1); - done(); - }); - }); - - test('.dataFrame() w/o fin should generate correct frame', function() { - var frame = framer.dataFrame(1, false, new Buffer(123)); - assert.equal(frame[4], 0); - assert.ok(frame.length > 8); - }); - - test('.dataFrame() with fin should generate correct frame', function() { - var frame = framer.dataFrame(1, true, new Buffer(123)); - assert.equal(frame[4], 1); - assert.ok(frame.length > 8); - }); - - test('.pingFrame() should generate correct frame', function() { - var frame = framer.pingFrame(new Buffer([0, 1, 2, 3])); - assert.ok(frame.length > 0); - }); - - test('.rstFrame() should generate correct frame', function() { - var frame = framer.rstFrame(1, 2); - assert.ok(frame.length > 0); - - // Verify that cache works - var frame = framer.rstFrame(1, 2); - assert.ok(frame.length > 0); - }); - }); -}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/parser-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/parser-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/parser-test.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/parser-test.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -var assert = require('assert'), - spdy = require('../../'), - Buffer = require('buffer').Buffer; - -suite('A Parser of SPDY module', function() { - var parser; - - [2,3].forEach(function(version) { - suite('version ' + version, function() { - setup(function() { - var deflate = spdy.utils.createDeflate(version), - inflate = spdy.utils.createInflate(version); - - parser = new spdy.parser.create({ - socket: { - setNoDelay: function() {} - }, - write: function() {} - }, deflate, inflate); - - parser.createFramer(version); - }); - - test('should wait for headers initially', function() { - assert.equal(parser.waiting, 8); - }); - - test('should update buffered property once given < 8 bytes', function() { - parser.write(new Buffer(5)); - assert.equal(parser.buffered, 5); - }); - - test('given SYN_STREAM header should start waiting for body', function() { - parser.write(new Buffer([ - 0x80, 0x02, 0x00, 0x01, // Control frame, version, type (SYN_STREAM) - 0x00, 0x00, 0x12, 0x34 - ])); - - assert.equal(parser.waiting, 0x1234); - assert.equal(parser.state.type, 'frame-body'); - assert.ok(parser.state.header.control); - assert.equal(parser.state.header.flags, 0); - assert.equal(parser.state.header.length, 0x1234); - }); - - test('given DATA header should start waiting for body', function() { - parser.write(new Buffer([ - 0x00, 0x00, 0x00, 0x01, // Data frame, stream ID - 0x00, 0x00, 0x12, 0x34 - ])); - - assert.equal(parser.waiting, 0x1234); - assert.equal(parser.state.type, 'frame-body'); - assert.ok(!parser.state.header.control); - assert.equal(parser.state.header.id, 1); - assert.equal(parser.state.header.flags, 0); - assert.equal(parser.state.header.length, 0x1234); - }); - - test('given chunked header should not fail', function() { - parser.write(new Buffer([ - 0x80, 0x02, 0x00, 0x01 // Control frame, version, type (SYN_STREAM) - ])); - assert.equal(parser.buffered, 4); - - parser.write(new Buffer([ - 0x00, 0x00, 0x12, 0x34 - ])); - assert.equal(parser.buffered, 0); - - assert.equal(parser.waiting, 0x1234); - assert.equal(parser.state.type, 'frame-body'); - assert.ok(parser.state.header.control); - assert.equal(parser.state.header.flags, 0); - assert.equal(parser.state.header.length, 0x1234); - }); - - test('given header and body should emit `frame`', function(done) { - parser.on('frame', function(frame) { - assert.ok(frame.type === 'DATA'); - assert.equal(frame.id, 1); - assert.equal(frame.data.length, 4); - assert.equal(frame.data[0], 0x01); - assert.equal(frame.data[1], 0x02); - assert.equal(frame.data[2], 0x03); - assert.equal(frame.data[3], 0x04); - done(); - }); - - parser.write(new Buffer([ - 0x00, 0x00, 0x00, 0x01, // Data frame, stream ID - 0x00, 0x00, 0x00, 0x04, - 0x01, 0x02, 0x03, 0x04 // Body - ])); - - // Waits for next frame - assert.equal(parser.waiting, 8); - assert.equal(parser.state.type, 'frame-head'); - }); - }); - }); -}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/plain-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/plain-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/plain-test.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/plain-test.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,142 @@ +var assert = require('assert'), + spdy = require('../../'), + keys = require('../fixtures/keys'), + http = require('http'), + tls = require('tls'), + Buffer = require('buffer').Buffer, + PORT = 8081; + +suite('A SPDY Server / Plain', function() { + var server; + setup(function(done) { + server = spdy.createServer({ plain: true, ssl: false }, function(req, res) { + res.end('ok'); + }); + + server.listen(PORT, done); + }); + + teardown(function(done) { + server.close(done); + }); + + test('should respond on regular http requests', function(done) { + var req = http.request({ + host: '127.0.0.1', + port: PORT, + path: '/', + method: 'GET', + agent: false, + rejectUnauthorized: false + }, function(res) { + res.on('data', function() { + // Ignore incoming data + }); + assert.equal(res.statusCode, 200); + done(); + }); + req.end(); + }); + + test('should respond on spdy requests', function(done) { + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + spdy: { + ssl: false, + plain: true, + version: 3 + } + }); + + var req = http.request({ + path: '/', + method: 'GET', + agent: agent, + }, function(res) { + res.on('data', function() { + // Ignore incoming data + }); + assert.equal(res.statusCode, 200); + agent.close(); + done(); + }); + req.end(); + }); + + test('should handle header values with colons', function(done) { + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + spdy: { + ssl: false, + plain: true + } + }); + + var refererValue = 'http://127.0.0.1:' + PORT + '/header-with-colon'; + + server.on('request', function(req) { + assert.equal(req.headers.referer, refererValue); + }); + + http.request({ + path: '/', + method: 'GET', + agent: agent, + headers: { 'referer': refererValue } + }, function(res) { + assert.equal(res.statusCode, 200); + agent.close(); + done(); + }).end(); + }); + + test('should send date header as default', function(done) { + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + spdy: { + ssl: false, + plain: true + } + }); + + http.request({ + path: '/', + method: 'GET', + agent: agent + }, function(res) { + assert.equal(typeof res.headers.date, 'string'); + agent.close(); + done(); + }).end(); + }); + + test('should not send date header if res.sendDate is false', function(done) { + var agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + spdy: { + ssl: false, + plain: true + } + }); + + server.removeAllListeners('request'); + server.on('request', function(req, res) { + res.sendDate = false; + res.end('ok'); + }); + + http.request({ + path: '/', + method: 'GET', + agent: agent + }, function(res) { + assert.equal(typeof res.headers.date, 'undefined'); + agent.close(); + done(); + }).end(); + }); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/proxy-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/proxy-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/proxy-test.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/proxy-test.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,70 @@ +var assert = require('assert'), + https = require('https'), + spdy = require('../../'), + keys = require('../fixtures/keys'), + net = require('net'), + url = require('url'), + PORT = 8081; + +suite('A SPDY server / Proxy', function() { + test('should emit connect event on CONNECT requests', function(done) { + var proxyServer = spdy.createServer(keys); + proxyServer.on('connect', function(req, socket) { + var srvUrl = url.parse('http://' + req.url); + var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, function() { + socket._lock(function() { + var headers = { + 'Connection': 'keep-alive', + 'Proxy-Agent': 'SPDY Proxy' + } + socket._spdyState.framer.replyFrame( + socket._spdyState.id, 200, "Connection Established", headers, + function (err, frame) { + socket.connection.write(frame); + socket._unlock(); + srvSocket.pipe(socket); + socket.pipe(srvSocket); + } + ); + }); + }); + }); + + proxyServer.listen(PORT, '127.0.0.1', function() { + var spdyAgent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + rejectUnauthorized: false + }); + + var options = { + method: 'CONNECT', + path: 'www.google.com:80', + agent: spdyAgent + }; + + var req = https.request(options); + req.end(); + + req.on('connect', function(res, socket) { + var googlePage = ""; + socket.write('GET / HTTP/1.1\r\n' + + 'Host: www.google.com:80\r\n' + + 'Connection: close\r\n' + + '\r\n'); + + socket.on('data', function(chunk) { + googlePage = googlePage + chunk.toString(); + }); + + socket.on('end', function() { + assert.notEqual(googlePage.search('google'), -1, + "Google page should contain string 'google'"); + spdyAgent.close(function() { + proxyServer.close(done); + }); + }); + }); + }); + }); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/server-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/server-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/server-test.js 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/server-test.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -var assert = require('assert'), - spdy = require('../../'), - keys = require('../fixtures/keys'), - https = require('https'), - tls = require('tls'),request - Buffer = require('buffer').Buffer; - -suite('A SPDY Server', function() { - var server; - setup(function(done) { - server = spdy.createServer(keys, function(req, res) { - res.end('ok'); - }); - - server.listen(8081, done); - }); - - teardown(function(done) { - server.once('close', done); - server.close(); - }); - - test('should respond on regular https requests', function(done) { - https.request({ - host: 'localhost', - port: 8081, - path: '/', - method: 'GET', - agent: false, - rejectUnauthorized: false - }, function(res) { - assert.equal(res.statusCode, 200); - done(); - }).end(); - }); - - test('should respond on spdy requests', function(done) { - var socket = tls.connect( - 8081, - 'localhost', - { NPNProtocols: ['spdy/2'], rejectUnauthorized: false }, - function() { - var deflate = spdy.utils.createDeflate(2), - chunks = [], - length = 0; - - deflate.on('data', function(chunk) { - chunks.push(chunk); - length += chunk.length; - }); - - // Deflate headers - deflate.write(new Buffer([ - 0x00, 0x04, // method, url, version = 3 fields - 0x00, 0x06, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // method - 0x00, 0x03, - 0x47, 0x45, 0x54, // get - 0x00, 0x03, - 0x75, 0x72, 0x6c, // url - 0x00, 0x01, - 0x2f, // '/' - 0x00, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // version - 0x00, 0x08, - 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, // HTTP/1.1 - 0x00, 0x04, - 0x68, 0x6f, 0x73, 0x74, // host - 0x00, 0x09, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74 //localhost - ])); - - deflate.flush(function() { - // StreamID + Associated StreamID - length += 10; - - // Headers - socket.write(new Buffer([ - 0x80, 0x02, 0x00, 0x01, // Control, Version, SYN_STREAM - 0x00, 0x00, 0x00, length, // Flags, length (1 byte in this case) - 0x00, 0x00, 0x00, 0x01, // StreamID - 0x00, 0x00, 0x00, 0x00, // Associated StreamID - 0x00, 0x00 // Priority + Unused - ])); - - // Write compressed headers - chunks.forEach(function(chunk) { - socket.write(chunk); - }); - }); - - var response = new Buffer(85), - offset = 0; - - socket.on('data', function(chunk) { - assert.ok(offset + chunk.length <= 85); - - chunk.copy(response, offset); - offset += chunk.length; - - if (offset === 85) { - var frames = []; - - offset = 0; - while (offset < response.length) { - var len = (response.readUInt32BE(offset + 4) & 0x00ffffff) + 8; - frames.push(response.slice(offset, offset + len)); - - offset += len; - } - - // SYN_STREAM frame - assert.ok(frames.some(function(frame) { - return frame[0] === 0x80 && // Control frame - frame[1] === 0x02 && // Version - frame.readUInt16BE(2) === 0x0002 && // SYN_STREAM - frame.readUInt32BE(8) === 0x0001; // StreamID - })); - - // Data frames - assert.ok(frames.some(function(frame) { - return frame[0] === 0x00 && // Data frame - frame.readUInt32BE(0) === 0x0001 && // StreamID - frame.slice(8).toString() === 'ok'; - })); - - socket.destroy(); - } - }); - - socket.on('close', function() { - done(); - }); - } - ); - - socket.on('error', function(err) { - console.error('Socket error: ' + err); - }); - - server.on('request', function(req, res) { - assert.equal(req.url, '/'); - assert.equal(req.method, 'GET'); - res.end('ok'); - }); - }); -}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/stream-test.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/stream-test.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/node-spdy/test/unit/stream-test.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/node-spdy/test/unit/stream-test.js 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,371 @@ +var assert = require('assert'), + zlib = require('zlib'), + spdy = require('../../'), + keys = require('../fixtures/keys'), + https = require('https'), + util = require('util'), + Buffer = require('buffer').Buffer, + PORT = 8081; + +suite('A SPDY Server / Stream', function() { + var server; + var agent; + var pair = null; + + suite('normal', function() { + run({}); + }); + suite('maxChunk = false', function() { + run({ maxChunk: false }); + }); + + function run(options) { + setup(function(done) { + var waiting = 2; + pair = { server: null, client: null }; + + server = spdy.createServer(util._extend(keys, options), + function(req, res) { + assert.equal(req.method, 'POST'); + pair.server = { req: req, res: res }; + + // Just to remove junk from stream's buffer + if (spdy.utils.isLegacy) + req.once('data', function(data) { + assert.equal(data.toString(), 'shame'); + if (--waiting === 0) + done(); + }); + else + req.once('readable', function() { + assert.equal(req.read().toString(), 'shame'); + if (--waiting === 0) + done(); + }); + + res.writeHead(200); + }); + + server.listen(PORT, function() { + agent = spdy.createAgent({ + host: '127.0.0.1', + port: PORT, + rejectUnauthorized: false + }); + + pair.client = { + req: https.request({ + path: '/', + method: 'POST', + agent: agent + }, function(res) { + pair.client.res = res; + if (--waiting === 0) + done(); + }), + res: null + }; + pair.client.req.write('shame'); + }); + }); + + teardown(function(done) { + pair = null; + agent.close(function() { + server.close(done); + }); + }); + + test('should support PING from client', function(done) { + agent.ping(done); + }); + + test('should support PING from server', function(done) { + pair.server.res.socket.ping(done); + }); + + test('piping a lot of data', function(done) { + var big = new Buffer(2 * 1024 * 1024); + for (var i = 0; i < big.length; i++) + big[i] = ~~(Math.random() * 256); + + var offset = 0; + if (spdy.utils.isLegacy) { + pair.client.res.on('data', function(chunk) { + for (var i = 0; i < chunk.length; i++) { + assert(i + offset < big.length); + assert.equal(big[i + offset], chunk[i]); + } + offset += i; + }); + } else { + pair.client.res.on('readable', function() { + var bigEcho = pair.client.res.read(big.length); + if (bigEcho) { + assert.equal(big.length, bigEcho.length); + for (var i = 0; i < big.length; i += 256) { + assert.equal(big.slice(i, i + 256).toString('hex'), + bigEcho.slice(i, i + 256).toString('hex')); + } + offset += bigEcho.length; + } + }); + } + pair.client.res.on('end', function() { + assert.equal(offset, big.length); + done(); + }); + + pair.server.req.pipe(pair.server.res); + pair.client.req.end(big); + }); + + test('destroy in the middle', function(done) { + var big = new Buffer(2 * 1024 * 1024); + for (var i = 0; i < big.length; i++) + big[i] = ~~(Math.random() * 256); + + var offset = 0; + pair.server.req.on('data', function(chunk) { + for (var i = 0; i < chunk.length; i++) { + assert(i + offset < big.length); + assert.equal(big[i + offset], chunk[i]); + } + offset += i; + }); + + pair.server.req.on('close', function() { + assert(offset < big.length); + done(); + }); + + pair.client.req.write(big.slice(0, big.length >> 1)); + pair.client.req.write(big.slice(big.length >> 1)); + pair.client.req.socket.destroy(); + }); + + test('destroySoon in the middle', function(done) { + var big = new Buffer(2 * 1024 * 1024); + for (var i = 0; i < big.length; i++) + big[i] = ~~(Math.random() * 256); + + var offset = 0; + pair.server.req.on('data', function(chunk) { + for (var i = 0; i < chunk.length; i++) { + assert(i + offset < big.length); + assert.equal(big[i + offset], chunk[i]); + } + offset += i; + }); + + pair.server.req.on('end', function() { + assert.equal(offset, big.length); + done(); + }); + + pair.client.req.write(big.slice(0, big.length >> 1)); + pair.client.req.write(big.slice(big.length >> 1)); + pair.client.req.socket.destroySoon(); + }); + + test('ending', function(done) { + var data = ''; + pair.server.req.on('data', function(chunk) { + data += chunk; + }); + + pair.server.req.on('end', function() { + assert.equal(data, 'hello'); + pair.server.res.end(); + done(); + }); + + pair.client.req.end('hello'); + }); + + test('trailing headers from client', function(done) { + pair.server.req.once('trailers', function(headers) { + assert.equal(headers.wtf, 'yes'); + assert.equal(pair.server.req.trailers.wtf, 'yes'); + done(); + }); + pair.client.req.addTrailers({ wtf: 'yes' }); + }); + + test('trailing headers from server', function(done) { + pair.client.res.once('trailers', function(headers) { + assert.equal(headers.wtf, 'yes'); + assert.equal(pair.client.res.trailers.wtf, 'yes'); + done(); + }); + pair.server.res.addTrailers({ wtf: 'yes' }); + }); + + test('push stream', function(done) { + agent.once('push', function(req) { + var gotTrailers = false; + assert.equal(req.headers.wtf, 'true'); + + var chunks = ''; + req.once('data', function(chunk) { + chunks += chunk; + }); + req.once('trailers', function(trailers) { + assert.equal(trailers.ok, 'yes'); + gotTrailers = true; + }); + req.once('end', function() { + assert(gotTrailers); + assert.equal(req.trailers.ok, 'yes'); + assert.equal(chunks, 'yes, wtf'); + done(); + }); + }); + + pair.server.res.push('/wtf', { wtf: true }, function(err, stream) { + assert(!err); + stream.on('error', function(err) { + throw err; + }); + stream.sendHeaders({ ok: 'yes' }); + stream.end('yes, wtf'); + }); + }); + + test('push stream with compression', function(done) { + agent.once('push', function(req) { + req.once('data', function(chunk) { + assert.equal(chunk.toString(), 'yes, wtf'); + done(); + }); + }); + pair.server.res.push('/wtf', { + 'Content-Encoding': 'gzip' + }, function(err, stream) { + assert(!err); + stream.on('error', function(err) { + throw err; + }); + var gzip = zlib.createGzip(); + gzip.on('data', function(data) { + stream.write(data); + }); + gzip.on('end', function() { + stream.end(); + }); + gzip.end('yes, wtf'); + }); + }); + + test('push stream - big chunks', function(done) { + var count = 10; + var chunk = new Buffer(256 * 1024 - 7); + for (var i = 0; i < chunk.length; i++) + chunk[i] = ~~(Math.random() * 256); + + agent.once('push', function(req) { + assert.equal(req.headers.wtf, 'true'); + var offset = 0; + var total = 0; + req.on('data', function(data) { + for (var i = 0; i < data.length; i++) { + assert.equal(data[i], + chunk[(offset + i) % chunk.length], + 'Mismatch at: ' + (offset + i)); + } + offset = (offset + i) % chunk.length; + total += i; + }); + req.once('end', function() { + assert.equal(total, count * chunk.length); + done(); + }); + }); + + pair.server.res.push('/wtf', { wtf: true }, function(err, stream) { + assert(!err); + stream.on('error', function(err) { + throw err; + }); + + function start(count) { + if (count === 1) + return stream.end(chunk); + stream.write(chunk); + setTimeout(function() { + start(count - 1); + }, 5); + } + start(count); + }); + }); + + test('push stream - early close', function(done) { + agent.once('push', function(req) { + var chunks = ''; + req.on('data', function(chunk) { + chunks += chunk; + }); + req.once('end', function() { + assert.equal(chunks, 'yes, wtf'); + done(); + }); + }); + var stream = pair.server.res.push('/wtf', {}); + pair.client.res.on('data', function() {}); + pair.client.res.once('end', function() { + stream.end('yes, wtf'); + }); + pair.client.req.end(); + pair.server.res.end(); + }); + + test('timing out', function(done) { + var data = ''; + + pair.server.req.socket.setTimeout(300); + pair.client.req.on('error', function() { + done(); + }); + }); + + test('timing out after write', function(done) { + var data = ''; + var chunks = 0; + + pair.server.req.socket.setTimeout(150); + setTimeout(function() { + pair.server.res.write('ok1'); + setTimeout(function() { + pair.server.res.write('ok2'); + }, 100); + }, 100); + + pair.client.res.on('data', function(chunk) { + chunk = chunk.toString(); + assert(chunks === 0 && chunk === 'ok1' || + chunks === 1 && chunk === 'ok2'); + chunks++; + }); + + pair.client.req.on('error', function() { + assert.equal(chunks, 2); + done(); + }); + }); + + test('req[spdyVersion/streamID]', function(done) { + var data = ''; + assert.equal(pair.server.req.spdyVersion, 3.1); + assert(pair.server.req.streamID > 0); + + pair.server.req.resume(); + pair.server.req.on('end', function() { + pair.server.res.end(); + done(); + }); + + pair.client.req.end(); + }); + } +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/runxpcshelltests.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/runxpcshelltests.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/runxpcshelltests.py 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/runxpcshelltests.py 2014-11-26 21:46:00.000000000 +0000 @@ -39,7 +39,6 @@ HAVE_PSUTIL = False from automation import Automation -from automationutils import addCommonOptions HARNESS_TIMEOUT = 5 * 60 @@ -1359,8 +1358,6 @@ def __init__(self): """Process command line arguments and call runTests() to do the real work.""" OptionParser.__init__(self) - - addCommonOptions(self) self.add_option("--app-path", type="string", dest="appPath", default=None, help="application directory (as opposed to XRE directory)") @@ -1417,6 +1414,26 @@ self.add_option("--failure-manifest", dest="failureManifest", action="store", help="path to file where failure manifest will be written.") + self.add_option("--xre-path", + action = "store", type = "string", dest = "xrePath", + # individual scripts will set a sane default + default = None, + help = "absolute path to directory containing XRE (probably xulrunner)") + self.add_option("--symbols-path", + action = "store", type = "string", dest = "symbolsPath", + default = None, + help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols") + self.add_option("--debugger", + action = "store", dest = "debugger", + help = "use the given debugger to launch the application") + self.add_option("--debugger-args", + action = "store", dest = "debuggerArgs", + help = "pass the given args to the debugger _before_ " + "the application on the command line") + self.add_option("--debugger-interactive", + action = "store_true", dest = "debuggerInteractive", + help = "prevents the test harness from redirecting " + "stdout and stderr for interactive debuggers") def main(): parser = XPCShellOptions() diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/selftest.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/selftest.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/testing/xpcshell/selftest.py 2014-11-14 09:37:26.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/testing/xpcshell/selftest.py 2014-11-26 21:46:00.000000000 +0000 @@ -76,7 +76,8 @@ add_test(function test_child_assert () { do_load_child_test_harness(); - sendCommand("Assert.ok(true);"); + do_test_pending("test child assertion"); + sendCommand("Assert.ok(true);", do_test_finished); run_next_test(); }); ''' @@ -470,7 +471,8 @@ def testChild(self): """ Checks that calling do_load_child_test_harness without run_test_in_child - results in a usable test state. + results in a usable test state. This test has a spurious failure when + run using |mach python-test|. See bug 1103226. """ self.writeFile("test_child_assertions.js", CHILD_HARNESS_SIMPLE) self.writeManifest(["test_child_assertions.js"]) @@ -508,6 +510,8 @@ self.assertTestResult(True, verbose=True) + @unittest.skipIf('MOZ_AUTOMATION' in os.environ, + 'Timeout code path occasionally times out (bug 1098121)') def testHangingTimeout(self): """ Check that a test that never finishes results in the correct error log. @@ -889,4 +893,4 @@ self.assertInLog("Throwing an error to force displaying the log") if __name__ == "__main__": - unittest.main() + unittest.main(verbosity=3) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/RemoteAddonsChild.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/RemoteAddonsChild.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/RemoteAddonsChild.jsm 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/RemoteAddonsChild.jsm 2014-11-26 21:46:00.000000000 +0000 @@ -325,8 +325,8 @@ this._instances[contractID] = instance; registrar.registerFactory(this._classID, this._classDescription, contractID, instance); } else { + registrar.unregisterFactory(this._classID, this._instances[contractID]); delete this._instances[contractID]; - registerFactory.unregisterFactory(this._classID, this); } }, }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/RemoteAddonsParent.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/RemoteAddonsParent.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/RemoteAddonsParent.jsm 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/RemoteAddonsParent.jsm 2014-11-26 21:46:00.000000000 +0000 @@ -109,20 +109,16 @@ .getService(Ci.nsIMessageBroadcaster); ppmm.addMessageListener("Addons:ContentPolicy:Run", this); - this._policies = []; + this._policies = new Map(); }, - addContentPolicy: function(cid) { - this._policies.push(cid); + addContentPolicy: function(name, cid) { + this._policies.set(name, cid); NotificationTracker.add(["content-policy"]); }, - removeContentPolicy: function(cid) { - let index = this._policies.lastIndexOf(cid); - if (index > -1) { - this._policies.splice(index, 1); - } - + removeContentPolicy: function(name) { + this._policies.delete(name); NotificationTracker.remove(["content-policy"]); }, @@ -135,8 +131,14 @@ }, shouldLoad: function(aData, aObjects) { - for (let policyCID of this._policies) { - let policy = Cc[policyCID].getService(Ci.nsIContentPolicy); + for (let policyCID of this._policies.values()) { + let policy; + try { + policy = Cc[policyCID].getService(Ci.nsIContentPolicy); + } catch (e) { + // Current Gecko behavior is to ignore entries that don't QI. + continue; + } try { let contentLocation = BrowserUtils.makeURI(aData.contentLocation); let requestOrigin = aData.requestOrigin ? BrowserUtils.makeURI(aData.requestOrigin) : null; @@ -167,7 +169,7 @@ CategoryManagerInterposition.methods.addCategoryEntry = function(addon, target, category, entry, value, persist, replace) { if (category == "content-policy") { - ContentPolicyParent.addContentPolicy(entry); + ContentPolicyParent.addContentPolicy(entry, value); } target.addCategoryEntry(category, entry, value, persist, replace); @@ -382,7 +384,7 @@ // Check if |target| is somewhere on the patch from the // up to the root element. let window = target.ownerDocument.defaultView; - if (target.contains(window.gBrowser)) { + if (window && target.contains(window.gBrowser)) { return window; } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/tests/addon/bootstrap.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/tests/addon/bootstrap.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/tests/addon/bootstrap.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/tests/addon/bootstrap.js 2014-11-26 21:46:00.000000000 +0000 @@ -3,6 +3,7 @@ var Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/BrowserUtils.jsm"); const baseURL = "http://mochi.test:8888/browser/" + "toolkit/components/addoncompat/tests/browser/"; @@ -232,6 +233,31 @@ }); } +// Test for bug 1095305. We just want to make sure that loading some +// unprivileged content from an add-on package doesn't crash. +function testAddonContent() +{ + let chromeRegistry = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + let base = chromeRegistry.convertChromeURL(BrowserUtils.makeURI("chrome://addonshim1/content/")); + + let res = Services.io.getProtocolHandler("resource") + .QueryInterface(Ci.nsIResProtocolHandler); + res.setSubstitution("addonshim1", base); + + return new Promise(function(resolve, reject) { + const url = "resource://addonshim1/page.html"; + let tab = gBrowser.addTab(url); + let browser = tab.linkedBrowser; + addLoadListener(browser, function handler() { + gBrowser.removeTab(tab); + res.setSubstitution("addonshim1", null); + + resolve(); + }); + }); +} + function runTests(win, funcs) { ok = funcs.ok; @@ -245,7 +271,8 @@ then(testListeners). then(testCapturing). then(testObserver). - then(testSandbox); + then(testSandbox). + then(testAddonContent); } /* diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/tests/addon/chrome.manifest thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/tests/addon/chrome.manifest --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/tests/addon/chrome.manifest 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/tests/addon/chrome.manifest 2014-11-26 21:46:00.000000000 +0000 @@ -1 +1 @@ -content addonshim1 content/ \ No newline at end of file +content addonshim1 content/ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/tests/addon/content/page.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/tests/addon/content/page.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/addoncompat/tests/addon/content/page.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/addoncompat/tests/addon/content/page.html 2014-11-26 21:46:00.000000000 +0000 @@ -0,0 +1,2 @@ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/alerts/nsAlertsService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/alerts/nsAlertsService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/alerts/nsAlertsService.cpp 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/alerts/nsAlertsService.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -100,10 +100,12 @@ nsCOMPtr sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); nsresult rv; if (sysAlerts) { - return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, - aAlertCookie, aAlertListener, aAlertName, - aBidi, aLang, aData, - IPC::Principal(aPrincipal)); + rv = sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, + aAlertCookie, aAlertListener, aAlertName, + aBidi, aLang, aData, + IPC::Principal(aPrincipal)); + if (NS_SUCCEEDED(rv)) + return NS_OK; } if (!ShouldShowAlert()) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/build/nsToolkitCompsModule.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/build/nsToolkitCompsModule.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/build/nsToolkitCompsModule.cpp 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/build/nsToolkitCompsModule.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -4,7 +4,6 @@ #include "mozilla/ModuleUtils.h" #include "nsAppStartup.h" -#include "nsTerminator.h" #include "nsUserInfo.h" #include "nsToolkitCompsCID.h" #include "nsFindService.h" @@ -44,12 +43,23 @@ #include "NativeFileWatcherNotSupported.h" #endif // (XP_WIN) +#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID) +#define MOZ_HAS_TERMINATOR +#endif + +#if defined(MOZ_HAS_TERMINATOR) +#include "nsTerminator.h" +#endif + using namespace mozilla; ///////////////////////////////////////////////////////////////////////////// NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAppStartup, Init) + +#if defined(MOZ_HAS_TERMINATOR) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTerminator) +#endif NS_GENERIC_FACTORY_CONSTRUCTOR(nsUserInfo) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFindService) @@ -105,7 +115,9 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AddonPathService, AddonPathService::GetInstance) NS_DEFINE_NAMED_CID(NS_TOOLKIT_APPSTARTUP_CID); +#if defined(MOZ_HAS_TERMINATOR) NS_DEFINE_NAMED_CID(NS_TOOLKIT_TERMINATOR_CID); +#endif NS_DEFINE_NAMED_CID(NS_USERINFO_CID); NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID); #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS) @@ -134,7 +146,9 @@ static const Module::CIDEntry kToolkitCIDs[] = { { &kNS_TOOLKIT_APPSTARTUP_CID, false, nullptr, nsAppStartupConstructor }, +#if defined(MOZ_HAS_TERMINATOR) { &kNS_TOOLKIT_TERMINATOR_CID, false, nullptr, nsTerminatorConstructor }, +#endif { &kNS_USERINFO_CID, false, nullptr, nsUserInfoConstructor }, { &kNS_ALERTSSERVICE_CID, false, nullptr, nsAlertsServiceConstructor }, #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS) @@ -165,7 +179,9 @@ static const Module::ContractIDEntry kToolkitContracts[] = { { NS_APPSTARTUP_CONTRACTID, &kNS_TOOLKIT_APPSTARTUP_CID }, +#if defined(MOZ_HAS_TERMINATOR) { NS_TOOLKIT_TERMINATOR_CONTRACTID, &kNS_TOOLKIT_TERMINATOR_CID }, +#endif { NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID }, { NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID }, #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/nsDownloadManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/nsDownloadManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/nsDownloadManager.cpp 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/nsDownloadManager.cpp 2014-11-26 21:46:00.000000000 +0000 @@ -37,6 +37,8 @@ #include "nsEmbedCID.h" #include "nsToolkitCompsCID.h" +#include "mozilla/net/ReferrerPolicy.h" + #include "SQLFunctions.h" #include "mozilla/Preferences.h" @@ -1859,7 +1861,10 @@ dl->mCancelable = wbp; (void)wbp->SetProgressListener(dl); - rv = wbp->SavePrivacyAwareURI(dl->mSource, nullptr, nullptr, nullptr, nullptr, + // referrer policy can be anything since referrer is nullptr + rv = wbp->SavePrivacyAwareURI(dl->mSource, nullptr, + nullptr, mozilla::net::RP_Default, + nullptr, nullptr, dl->mTarget, dl->mPrivate); if (NS_FAILED(rv)) { dl->mCancelable = nullptr; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/head_download_manager.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/head_download_manager.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/head_download_manager.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/head_download_manager.js 2014-11-26 21:46:00.000000000 +0000 @@ -113,7 +113,7 @@ aParams.runBeforeStart.call(undefined, dl); persist.progressListener = dl.QueryInterface(Ci.nsIWebProgressListener); - persist.savePrivacyAwareURI(dl.source, null, null, null, null, dl.targetFile, + persist.savePrivacyAwareURI(dl.source, null, null, 0, null, null, dl.targetFile, aParams.isPrivate); return dl; @@ -230,4 +230,4 @@ return true; } return false; -} \ No newline at end of file +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_bug_420230.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_bug_420230.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_bug_420230.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_bug_420230.js 2014-11-26 21:46:00.000000000 +0000 @@ -40,7 +40,7 @@ Math.round(Date.now() * 1000), null, persist, false); persist.progressListener = dl.QueryInterface(Ci.nsIWebProgressListener); - persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); + persist.saveURI(dl.source, null, null, 0, null, null, dl.targetFile, null); return dl; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_offline_support.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_offline_support.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_offline_support.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_offline_support.js 2014-11-26 21:46:00.000000000 +0000 @@ -152,7 +152,7 @@ createURI(destFile), null, null, Math.round(Date.now() * 1000), null, persist, false); persist.progressListener = dl.QueryInterface(nsIWPL); - persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); + persist.saveURI(dl.source, null, null, 0, null, null, dl.targetFile, null); // Mark as pending, so clear this when we actually finish the download do_test_pending(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_resume.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_resume.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_resume.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_resume.js 2014-11-26 21:46:00.000000000 +0000 @@ -131,7 +131,7 @@ createURI(destFile), null, null, Math.round(Date.now() * 1000), null, persist, false); persist.progressListener = dl.QueryInterface(nsIWPL); - persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); + persist.saveURI(dl.source, null, null, 0, null, null, dl.targetFile, null); // Mark as pending, so clear this when we actually finish the download do_test_pending(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_sleep_wake.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_sleep_wake.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/downloads/test/unit/test_sleep_wake.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/downloads/test/unit/test_sleep_wake.js 2014-11-26 21:46:00.000000000 +0000 @@ -152,7 +152,7 @@ createURI(destFile), null, null, Math.round(Date.now() * 1000), null, persist, false); persist.progressListener = dl.QueryInterface(nsIWPL); - persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); + persist.saveURI(dl.source, null, null, 0, null, null, dl.targetFile, null); // Mark as pending, so clear this when we actually finish the download do_test_pending(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/jsdownloads/src/DownloadCore.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/jsdownloads/src/DownloadCore.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/jsdownloads/src/DownloadCore.jsm 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/jsdownloads/src/DownloadCore.jsm 2014-11-26 21:46:00.000000000 +0000 @@ -477,6 +477,16 @@ // Update the download error, unless a new attempt already started. The // change in the status property is notified in the finally block. if (this._currentAttempt == currentAttempt || !this._currentAttempt) { + if (!(ex instanceof DownloadError)) { + let properties = {innerException: ex}; + + if (ex.message) { + properties.message = ex.message; + } + + ex = new DownloadError(properties); + } + this.error = ex; } throw ex; @@ -910,8 +920,8 @@ serializable.saver = saver; } - if (this.error && ("message" in this.error)) { - serializable.error = { message: this.error.message }; + if (this.error) { + serializable.errorObj = this.error.toSerializable(); } if (this.startTime) { @@ -919,8 +929,8 @@ } // These are serialized unless they are false, null, or empty strings. - for (let property of kSerializableDownloadProperties) { - if (property != "error" && property != "startTime" && this[property]) { + for (let property of kPlainSerializableDownloadProperties) { + if (this[property]) { serializable[property] = this[property]; } } @@ -953,10 +963,9 @@ /** * Defines which properties of the Download object are serializable. */ -const kSerializableDownloadProperties = [ +const kPlainSerializableDownloadProperties = [ "succeeded", "canceled", - "error", "totalBytes", "hasPartialData", "tryToKeepPartialData", @@ -1011,17 +1020,30 @@ download.startTime = new Date(time); } - for (let property of kSerializableDownloadProperties) { + // If 'errorObj' is present it will take precedence over the 'error' property. + // 'error' is a legacy property only containing message, which is insufficient + // to represent all of the error information. + // + // Instead of just replacing 'error' we use a new 'errorObj' so that previous + // versions will keep it as an unknown property. + if ("errorObj" in aSerializable) { + download.error = DownloadError.fromSerializable(aSerializable.errorObj); + } else if ("error" in aSerializable) { + download.error = aSerializable.error; + } + + for (let property of kPlainSerializableDownloadProperties) { if (property in aSerializable) { download[property] = aSerializable[property]; } } deserializeUnknownProperties(download, aSerializable, property => - kSerializableDownloadProperties.indexOf(property) == -1 && + kPlainSerializableDownloadProperties.indexOf(property) == -1 && property != "startTime" && property != "source" && property != "target" && + property != "error" && property != "saver"); return download; @@ -1263,6 +1285,10 @@ this.becauseBlocked = true; } + if (aProperties.innerException) { + this.innerException = aProperties.innerException; + } + this.stack = new Error().stack; } @@ -1301,6 +1327,56 @@ * and may be malware. */ becauseBlockedByReputationCheck: false, + + /** + * If this DownloadError was caused by an exception this property will + * contain the original exception. This will not be serialized when saving + * to the store. + */ + innerException: null, + + /** + * Returns a static representation of the current object state. + * + * @return A JavaScript object that can be serialized to JSON. + */ + toSerializable: function () + { + let serializable = { + result: this.result, + message: this.message, + becauseSourceFailed: this.becauseSourceFailed, + becauseTargetFailed: this.becauseTargetFailed, + becauseBlocked: this.becauseBlocked, + becauseBlockedByParentalControls: this.becauseBlockedByParentalControls, + becauseBlockedByReputationCheck: this.becauseBlockedByReputationCheck, + }; + + serializeUnknownProperties(this, serializable); + return serializable; + }, +}; + +/** + * Creates a new DownloadError object from its serializable representation. + * + * @param aSerializable + * Serializable representation of a DownloadError object. + * + * @return The newly created DownloadError object. + */ +this.DownloadError.fromSerializable = function (aSerializable) { + let e = new DownloadError(aSerializable); + deserializeUnknownProperties(e, aSerializable, property => + property != "result" && + property != "message" && + property != "becauseSourceFailed" && + property != "becauseTargetFailed" && + property != "becauseBlocked" && + property != "becauseBlockedByParentalControls" && + property != "becauseBlockedByReputationCheck"); + + return e; }; //////////////////////////////////////////////////////////////////////////////// diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/jsdownloads/test/unit/head.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/jsdownloads/test/unit/head.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/jsdownloads/test/unit/head.js 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/jsdownloads/test/unit/head.js 2014-11-26 21:46:00.000000000 +0000 @@ -391,7 +391,7 @@ persist.progressListener = transfer; // Start the actual download process. - persist.savePrivacyAwareURI(sourceURI, null, null, null, null, targetFile, + persist.savePrivacyAwareURI(sourceURI, null, null, 0, null, null, targetFile, isPrivate); }.bind(this)).then(null, do_report_unexpected_exception); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/moz.build 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/moz.build 2014-11-26 21:46:00.000000000 +0000 @@ -45,7 +45,6 @@ 'startup', 'statusfilter', 'telemetry', - 'terminator', 'thumbnails', 'typeaheadfind', 'urlformatter', @@ -86,6 +85,9 @@ if CONFIG['MOZ_CAPTIVEDETECT']: DIRS += ['captivedetect'] +if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk" and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': + DIRS += ['terminator'] + DIRS += ['build'] EXTRA_COMPONENTS += [ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/modules/osfile_async_front.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/modules/osfile_async_front.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/modules/osfile_async_front.jsm 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/modules/osfile_async_front.jsm 2014-11-26 21:46:00.000000000 +0000 @@ -619,39 +619,6 @@ }, /** - * Read a number of bytes from the file and into a buffer. - * - * @param {Typed array | C pointer} buffer This buffer will be - * modified by another thread. Using this buffer before the |read| - * operation has completed is a BAD IDEA. - * @param {JSON} options - * - * @return {promise} - * @resolves {number} The number of bytes effectively read. - * @rejects {OS.File.Error} - */ - readTo: function readTo(buffer, options = {}) { - // If |buffer| is a typed array and there is no |bytes| options, we - // need to extract the |byteLength| now, as it will be lost by - // communication. - // Options might be a nullish value, so better check for that before using - // the |in| operator. - if (isTypedArray(buffer) && !(options && "bytes" in options)) { - // Preserve reference to option |outExecutionDuration|, if it is passed. - options = clone(options, ["outExecutionDuration"]); - options.bytes = buffer.byteLength; - } - // Note: Type.void_t.out_ptr.toMsg ensures that - // - the buffer is effectively shared (not neutered) between both - // threads; - // - we take care of any |byteOffset|. - return Scheduler.post("File_prototype_readTo", - [this._fdmsg, - Type.void_t.out_ptr.toMsg(buffer), - options], - buffer/*Ensure that |buffer| is not gc-ed*/); - }, - /** * Write bytes from a buffer to this file. * * Note that, by default, this function may perform several I/O diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/modules/osfile_shared_front.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/modules/osfile_shared_front.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/modules/osfile_shared_front.jsm 2014-11-14 09:37:27.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/modules/osfile_shared_front.jsm 2014-11-26 21:46:00.000000000 +0000 @@ -52,43 +52,22 @@ /** * Read bytes from this file to a new buffer. * - * @param {number=} bytes If unspecified, read all the remaining bytes from - * this file. If specified, read |bytes| bytes, or less if the file does notclone - * contain that many bytes. + * @param {number=} maybeBytes (deprecated, please use options.bytes) * @param {JSON} options * @return {Uint8Array} An array containing the bytes read. */ - read: function read(bytes, options = {}) { - options = clone(options); - options.bytes = bytes == null ? this.stat().size : bytes; - let buffer = new Uint8Array(options.bytes); - let size = this.readTo(buffer, options); - if (size == options.bytes) { - return buffer; + read: function read(maybeBytes, options = {}) { + if (typeof maybeBytes === "object") { + // Caller has skipped `maybeBytes` and provided an options object. + options = clone(maybeBytes); + maybeBytes = null; } else { - return buffer.subarray(0, size); + options = clone(options || {}); } - }, - - /** - * Read bytes from this file to an existing buffer. - * - * Note that, by default, this function may perform several I/O - * operations to ensure that the buffer is as full as possible. - * - * @param {Typed Array | C pointer} buffer The buffer in which to - * store the bytes. The buffer must be large enough to - * accomodate |bytes| bytes. - * @param {*=} options Optionally, an object that may contain the - * following fields: - * - {number} bytes The number of |bytes| to write from the buffer. If - * unspecified, this is |buffer.byteLength|. Note that |bytes| is required - * if |buffer| is a C pointer. - * - * @return {number} The number of bytes actually read, which may be - * less than |bytes| if the file did not contain that many bytes left. - */ - readTo: function readTo(buffer, options = {}) { + if(!("bytes" in options)) { + options.bytes = maybeBytes == null ? this.stat().size : maybeBytes; + } + let buffer = new Uint8Array(options.bytes); let {ptr, bytes} = SharedAll.normalizeToPointer(buffer, options.bytes); let pos = 0; while (pos < bytes) { @@ -99,8 +78,11 @@ pos += chunkSize; ptr = SharedAll.offsetBy(ptr, chunkSize); } - - return pos; + if (pos == options.bytes) { + return buffer; + } else { + return buffer.subarray(0, pos); + } }, /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js 2014-11-26 21:46:00.000000000 +0000 @@ -152,7 +152,6 @@ yield test_stat(); yield test_debug(); yield test_info_features_detect(); - yield test_read_write(); yield test_position(); yield test_iter(); yield test_exists(); @@ -221,62 +220,6 @@ }); /** - * Test OS.File.prototype.{read, readTo, write} - */ -let test_read_write = maketest("read_write", function read_write(test) { - return Task.spawn(function() { - // Test readTo/write - let currentDir = yield OS.File.getCurrentDirectory(); - let pathSource = OS.Path.join(currentDir, EXISTING_FILE); - let pathDest = OS.Path.join(OS.Constants.Path.tmpDir, - "osfile async test.tmp"); - - let fileSource = yield OS.File.open(pathSource); - test.info("Input file opened"); - let fileDest = yield OS.File.open(pathDest, - { truncate: true, read: true, write: true}); - test.info("Output file opened"); - - let stat = yield fileSource.stat(); - test.info("Input stat worked"); - let size = stat.size; - let array = new Uint8Array(size); - - try { - test.info("Now calling readTo"); - let readLength = yield fileSource.readTo(array); - test.info("ReadTo worked"); - test.is(readLength, size, "ReadTo got all bytes"); - let writeLength = yield fileDest.write(array); - test.info("Write worked"); - test.is(writeLength, size, "Write wrote all bytes"); - - // Test read - yield fileSource.setPosition(0); - let readAllResult = yield fileSource.read(); - test.info("ReadAll worked"); - test.is(readAllResult.length, size, "ReadAll read all bytes"); - test.is(Array.prototype.join.call(readAllResult), - Array.prototype.join.call(array), - "ReadAll result is correct"); - } finally { - // Close stuff - yield fileSource.close(); - yield fileDest.close(); - test.info("Files are closed"); - } - - stat = yield OS.File.stat(pathDest); - test.is(stat.size, size, "Both files have the same size"); - yield reference_compare_files(pathSource, pathDest, test); - - // Cleanup. - OS.File.remove(pathDest); - }); -}); - - -/** * Test file.{getPosition, setPosition} */ let test_position = maketest("position", function position(test) { @@ -284,13 +227,8 @@ let file = yield OS.File.open(EXISTING_FILE); try { - let stat = yield file.stat(); - test.info("Obtained file length"); - - let view = new Uint8Array(stat.size); - yield file.readTo(view); + let view = yield file.read(); test.info("First batch of content read"); - let CHUNK_SIZE = 178;// An arbitrary number of bytes to read from the file let pos = yield file.getPosition(); test.info("Obtained position"); @@ -299,8 +237,7 @@ test.info("Changed position"); test.is(pos, view.byteLength - CHUNK_SIZE, "setPosition returned the correct position"); - let view2 = new Uint8Array(CHUNK_SIZE); - yield file.readTo(view2); + let view2 = yield file.read(); test.info("Read the end of the file"); for (let i = 0; i < CHUNK_SIZE; ++i) { if (view2[i] != view[i + view.byteLength - CHUNK_SIZE]) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js 2014-11-26 21:46:00.000000000 +0000 @@ -27,7 +27,6 @@ test_open_non_existing_file(); test_flush_open_file(); test_copy_existing_file(); - test_readall_writeall_file(); test_position(); test_move_file(); test_iter_dir(); @@ -184,190 +183,6 @@ info(test + ": Comparison complete"); } -function test_readall_writeall_file() -{ - let src_file_name = - OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", - "worker_test_osfile_front.js"); - let tmp_file_name = - OS.Path.join(OS.Constants.Path.tmpDir, "test_osfile_front.tmp"); - info("Starting test_readall_writeall_file"); - - // read, ArrayBuffer - - let source = OS.File.open(src_file_name); - let dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); - let size = source.stat().size; - - let buf = new Uint8Array(size); - let readResult = source.readTo(buf); - is(readResult, size, "test_readall_writeall_file: read the right number of bytes"); - - dest.write(buf); - - info("test_readall_writeall_file: copy complete (manual allocation)"); - source.close(); - dest.close(); - - compare_files("test_readall_writeall_file (manual allocation)", src_file_name, tmp_file_name); - OS.File.remove(tmp_file_name); - - // read, C buffer - source = OS.File.open(src_file_name); - dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); - buf = new ArrayBuffer(size); - let ptr = OS.Shared.Type.voidptr_t.implementation(buf); - readResult = source.readTo(ptr, {bytes: size}); - is(readResult, size, "test_readall_writeall_file: read the right number of bytes (C buffer)"); - - dest.write(ptr, {bytes: size}); - - info("test_readall_writeall_file: copy complete (C buffer)"); - source.close(); - dest.close(); - - compare_files("test_readall_writeall_file (C buffer)", src_file_name, tmp_file_name); - OS.File.remove(tmp_file_name); - - // read/write, C buffer, missing |bytes| option - source = OS.File.open(src_file_name); - dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); - let exn = should_throw(function() { source.readTo(ptr); }); - ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: read with C pointer and without bytes fails with the correct error"); - exn = should_throw(function() { dest.write(ptr); }); - ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: write with C pointer and without bytes fails with the correct error"); - - source.close(); - dest.close(); - - // readTo, ArrayBuffer + offset - let OFFSET = 12; - let LEFT = size - OFFSET; - buf = new ArrayBuffer(size); - let offset_view = new Uint8Array(buf, OFFSET); - source = OS.File.open(src_file_name); - dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); - - readResult = source.readTo(offset_view); - is(readResult, LEFT, "test_readall_writeall_file: read the right number of bytes (with offset)"); - - dest.write(offset_view); - is(dest.stat().size, LEFT, "test_readall_writeall_file: wrote the right number of bytes (with offset)"); - - info("test_readall_writeall_file: copy complete (with offset)"); - source.close(); - dest.close(); - - compare_files("test_readall_writeall_file (with offset)", src_file_name, tmp_file_name, LEFT); - OS.File.remove(tmp_file_name); - - // read - buf = new Uint8Array(size); - source = OS.File.open(src_file_name); - dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); - - readResult = source.read(); - is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (auto allocation)"); - - dest.write(readResult); - - info("test_readall_writeall_file: copy complete (auto allocation)"); - source.close(); - dest.close(); - - compare_files("test_readall_writeall_file (auto allocation)", src_file_name, tmp_file_name); - OS.File.remove(tmp_file_name); - - // File.readAll - readResult = OS.File.read(src_file_name); - is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (OS.File.readAll)"); - - // File.writeAtomic on top of nothing - OS.File.writeAtomic(tmp_file_name, readResult, - {tmpPath: tmp_file_name + ".tmp"}); - try { - let stat = OS.File.stat(tmp_file_name); - info("readAll + writeAtomic created a file"); - is(stat.size, size, "readAll + writeAtomic created a file of the right size"); - } catch (x) { - ok(false, "readAll + writeAtomic somehow failed"); - if(x.becauseNoSuchFile) { - ok(false, "readAll + writeAtomic did not create file"); - } - } - compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic)", - src_file_name, tmp_file_name); - exn = null; - try { - let stat = OS.File.stat(tmp_file_name + ".tmp"); - } catch (x) { - exn = x; - } - ok(!!exn, "readAll + writeAtomic cleaned up after itself"); - - // File.writeAtomic on top of existing file - // Remove content and set arbitrary size, to avoid potential false negatives - dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); - dest.setPosition(1234); - dest.close(); - - OS.File.writeAtomic(tmp_file_name, readResult, - {tmpPath: tmp_file_name + ".tmp"}); - compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic 2)", - src_file_name, tmp_file_name); - - // File.writeAtomic on top of existing file but without overwritten the file - exn = null; - try { - let view = new Uint8Array(readResult.buffer, 10, 200); - OS.File.writeAtomic(tmp_file_name, view, - { tmpPath: tmp_file_name + ".tmp", noOverwrite: true}); - } catch (x) { - exn = x; - } - ok(exn && exn instanceof OS.File.Error && exn.becauseExists, "writeAtomic fails if file already exists with noOverwrite option"); - // Check file was not overwritten. - compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic check file was not overwritten)", - src_file_name, tmp_file_name); - - // Ensure that File.writeAtomic fails if no temporary file name is provided - // (FIXME: Remove this test as part of bug 793660) - - exn = null; - try { - OS.File.writeAtomic(tmp_file_name, readResult.buffer, - {bytes: readResult.length}); - } catch (x) { - exn = x; - } - ok(!!exn && exn instanceof TypeError, "writeAtomic fails if tmpPath is not provided"); - - // Check that writeAtomic fails when destination path is undefined - exn = null; - try { - let path = undefined; - let options = {tmpPath: tmp_file_name}; - OS.File.writeAtomic(path, readResult.buffer, options); - } catch (x) { - exn = x; - } - ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is undefined"); - - // Check that writeAtomic fails when destination path is an empty string - exn = null; - try { - let path = ""; - let options = {tmpPath: tmp_file_name}; - OS.File.writeAtomic(path, readResult.buffer, options); - } catch (x) { - exn = x; - } - ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is an empty string"); - - // Cleanup. - OS.File.remove(tmp_file_name); -} - /** * Test that copying a file using |copy| works. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/tests/xpcshell/test_osfile_async_bytes.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/tests/xpcshell/test_osfile_async_bytes.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/osfile/tests/xpcshell/test_osfile_async_bytes.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/osfile/tests/xpcshell/test_osfile_async_bytes.js 2014-11-26 21:46:00.000000000 +0000 @@ -9,7 +9,7 @@ } /** - * Test to ensure that {bytes:} in options to |readTo| and |write| are correctly + * Test to ensure that {bytes:} in options to |write| is correctly * preserved. */ add_task(function* test_bytes() { @@ -23,12 +23,7 @@ yield file.write(new Uint8Array(2048), {bytes: 1024}); do_check_eq((yield file.stat()).size, 1024); - // 2. Test same for |readTo|. - yield file.setPosition(0, OS.File.POS_START); - let read = yield file.readTo(new Uint8Array(1024), {bytes: 512}); - do_check_eq(read, 512); - - // 3. Test that passing nullish values for |options| still works. + // 2. Test that passing nullish values for |options| still works. yield file.setPosition(0, OS.File.POS_END); yield file.write(new Uint8Array(1024), null); yield file.write(new Uint8Array(1024), undefined); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/Bookmarks.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/Bookmarks.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/Bookmarks.jsm 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/Bookmarks.jsm 2014-11-26 21:46:01.000000000 +0000 @@ -94,7 +94,7 @@ TYPE_SEPARATOR: 3, /** - * Default index used to append a bookmark-item at the end of a folder. + * Default index used to append a bookmark-item at the end of a folder. * This should stay consistent with nsINavBookmarksService.idl */ DEFAULT_INDEX: -1, @@ -238,7 +238,7 @@ let updateInfo = validateBookmarkObject(info, { guid: { required: true } , index: { requiredIf: b => b.hasOwnProperty("parentGuid") - , validIf: b => b.index >= 0 } + , validIf: b => b.index >= 0 || b.index == this.DEFAULT_INDEX } , parentGuid: { requiredIf: b => b.hasOwnProperty("index") } }); @@ -307,9 +307,15 @@ // the same container. Thus we know it exists. if (!parent) parent = yield fetchBookmark({ guid: item.parentGuid }); - // Set index in the appending case. - if (updateInfo.index > parent._childCount) - updateInfo.index = parent._childCount; + + if (updateInfo.index >= parent._childCount || + updateInfo.index == this.DEFAULT_INDEX) { + updateInfo.index = parent._childCount; + + // Fix the index when moving within the same container. + if (parent.guid == item.parentGuid) + updateInfo.index--; + } } let updatedItem = yield updateBookmark(updateInfo, item, parent); @@ -364,14 +370,14 @@ updatedItem.guid, updatedItem.parentGuid ]); } - // If the item was move, notify onItemMoved. + // If the item was moved, notify onItemMoved. if (item.parentGuid != updatedItem.parentGuid || item.index != updatedItem.index) { notify(observers, "onItemMoved", [ updatedItem._id, item._parentId, item.index, updatedItem._parentId, updatedItem.index, updatedItem.type, updatedItem.guid, item.parentGuid, - updatedItem.newParentGuid ]); + updatedItem.parentGuid ]); } // Remove non-enumerable properties. @@ -975,8 +981,10 @@ LEFT JOIN moz_keywords k ON k.id = b.keyword_id LEFT JOIN moz_places h ON h.id = b.fk WHERE h.url = :url + AND _grandParentId <> :tags_folder ORDER BY b.lastModified DESC - `, { url: info.url.href }); + `, { url: info.url.href, + tags_folder: PlacesUtils.tagsFolderId }); return rows.length ? rowsToItemsArray(rows) : null; } @@ -1158,7 +1166,7 @@ } return item; - }); + }); } /** @@ -1267,7 +1275,7 @@ } } if (required.size > 0) - throw new Error(`The following properties were expected: ${[...required].join(", ")}`); + throw new Error(`The following properties were expected: ${[...required].join(", ")}`); return normalizedInput; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/History.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/History.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/History.jsm 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/History.jsm 2014-11-26 21:46:01.000000000 +0000 @@ -65,6 +65,8 @@ const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown", + "resource://gre/modules/AsyncShutdown.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", @@ -83,6 +85,21 @@ Cu.importGlobalProperties(["URL"]); /** + * Whenever we update or remove numerous pages, it is preferable + * to yield time to the main thread every so often to avoid janking. + * This constant determines the maximal number of notifications we + * may emit before we yield. + */ +const NOTIFICATION_CHUNK_SIZE = 300; + +/** + * Private shutdown barrier blocked by ongoing operations. + */ +XPCOMUtils.defineLazyGetter(this, "operationsBarrier", () => + new AsyncShutdown.Barrier("Sqlite.jsm: wait until all connections are closed") +); + +/** * Shared connection */ XPCOMUtils.defineLazyGetter(this, "DBConnPromised", @@ -90,8 +107,19 @@ Sqlite.wrapStorageConnection({ connection: PlacesUtils.history.DBConnection } ) .then(db => { try { - Sqlite.shutdown.addBlocker("Places History.jsm: Closing database wrapper", - () => db.close()); + Sqlite.shutdown.addBlocker( + "Places History.jsm: Closing database wrapper", + Task.async(function*() { + yield operationsBarrier.wait(); + gIsClosed = true; + yield db.close(); + }), + () => ({ + fetchState: () => ({ + isClosed: gIsClosed, + operations: operationsBarrier.state, + }) + })); } catch (ex) { // It's too late to block shutdown of Sqlite, so close the connection // immediately. @@ -103,6 +131,34 @@ }) ); +/** + * `true` once this module has been shutdown. + */ +let gIsClosed = false; +function ensureModuleIsOpen() { + if (gIsClosed) { + throw new Error("History.jsm has been shutdown"); + } +} + +/** + * Sends a bookmarks notification through the given observers. + * + * @param observers + * array of nsINavBookmarkObserver objects. + * @param notification + * the notification name. + * @param args + * array of arguments to pass to the notification. + */ +function notify(observers, notification, args) { + for (let observer of observers) { + try { + observer[notification](...args); + } catch (ex) {} + } +} + this.History = Object.freeze({ /** * Fetch the available information for one page. @@ -209,6 +265,8 @@ * is an empty array. */ remove: function (pages, onResult = null) { + ensureModuleIsOpen(); + // Normalize and type-check arguments if (Array.isArray(pages)) { if (pages.length == 0) { @@ -230,6 +288,8 @@ urls.push(normalized.href); } } + let normalizedPages = {guids: guids, urls: urls}; + // At this stage, we know that either `guids` is not-empty // or `urls` is not-empty. @@ -237,8 +297,29 @@ throw new TypeError("Invalid function: " + onResult); } - // Now perform queries - return remove({guids: guids, urls: urls}, onResult); + return Task.spawn(function*() { + let promise = remove(normalizedPages, onResult); + + operationsBarrier.client.addBlocker( + "History.remove", + promise, + { + // In case of crash, we do not want to upload information on + // which urls are being cleared, for privacy reasons. GUIDs + // are safe wrt privacy, but useless. + fetchState: () => ({ + guids: guids.length, + urls: normalizedPages.urls.map(u => u.protocol), + }) + }); + + try { + return (yield promise); + } finally { + // Cleanup the barrier. + operationsBarrier.client.removeBlocker(promise); + } + }); }, /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/mozIAsyncLivemarks.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/mozIAsyncLivemarks.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/mozIAsyncLivemarks.idl 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/mozIAsyncLivemarks.idl 2014-11-26 21:46:01.000000000 +0000 @@ -101,7 +101,7 @@ in mozILivemark aLivemark); }; -[scriptable, uuid(6e40d5b1-ce48-4458-8b68-6bee17d30ef3)] +[scriptable, uuid(E52B2273-729D-4EBC-A039-E9CD9E18FF86)] interface mozILivemarkInfo : nsISupports { /** @@ -130,6 +130,11 @@ readonly attribute long index; /** + * Time this livemark was created. + */ + readonly attribute PRTime dateAdded; + + /** * Time this livemark's details were last modified. Doesn't track changes to * the livemark contents. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsINavBookmarksService.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsINavBookmarksService.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsINavBookmarksService.idl 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsINavBookmarksService.idl 2014-11-26 21:46:01.000000000 +0000 @@ -113,8 +113,7 @@ * For certain properties, this is set to the new value of the * property (see the list below). * @param aLastModified - * If lastModified changed, this parameter is the new value, otherwise - * it's set to 0. + * The updated last-modified value. * @param aItemType * The type of the item to be removed (see TYPE_* constants below). * @param aParentId diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsINavHistoryService.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsINavHistoryService.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsINavHistoryService.idl 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsINavHistoryService.idl 2014-11-26 21:46:01.000000000 +0000 @@ -1176,7 +1176,7 @@ nsINavHistoryQueryOptions clone(); }; -[scriptable, uuid(47f7b08b-71e0-492e-a2be-9a9fbfc75250)] +[scriptable, uuid(8a1f527e-c9d7-4a51-bf0c-d86f0379b701)] interface nsINavHistoryService : nsISupports { /** @@ -1374,6 +1374,12 @@ void removeObserver(in nsINavHistoryObserver observer); /** + * Gets an array of registered nsINavHistoryObserver objects. + */ + void getObservers([optional] out unsigned long count, + [retval, array, size_is(count)] out nsINavHistoryObserver observers); + + /** * Runs the passed callback in batch mode. Use this when a lot of things * are about to change. Calls can be nested, observers will only be * notified when all batches begin/end. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsLivemarkService.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsLivemarkService.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsLivemarkService.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsLivemarkService.js 2014-11-26 21:46:01.000000000 +0000 @@ -80,7 +80,8 @@ AND n.name = ${aAnnoParam}`; } - return `SELECT b.id, b.title, b.parent, b.position, b.guid, b.lastModified, + return `SELECT b.id, b.title, b.parent, b.position, b.guid, + b.dateAdded, b.lastModified, ( ${getAnnoSQLFragment(":feedURI_anno")} ) AS feedURI, ( ${getAnnoSQLFragment(":siteURI_anno")} ) AS siteURI FROM moz_bookmarks b @@ -106,6 +107,7 @@ title: row.getResultByName("title"), parentId: row.getResultByName("parent"), index: row.getResultByName("position"), + dateAdded: row.getResultByName("dateAdded"), lastModified: row.getResultByName("lastModified"), feedURI: NetUtil.newURI(row.getResultByName("feedURI")), siteURI: siteURL ? NetUtil.newURI(siteURL) : null }); @@ -202,11 +204,15 @@ , feedURI: aLivemarkInfo.feedURI , siteURI: aLivemarkInfo.siteURI , guid: aLivemarkInfo.guid + , dateAdded: aLivemarkInfo.dateAdded , lastModified: aLivemarkInfo.lastModified }); if (this._itemAdded && this._itemAdded.id == livemark.id) { livemark.index = this._itemAdded.index; livemark.guid = this._itemAdded.guid; + if (!aLivemarkInfo.dateAdded) { + livemark.dateAdded = this._itemAdded.dateAdded; + } if (!aLivemarkInfo.lastModified) { livemark.lastModified = this._itemAdded.lastModified; } @@ -411,6 +417,7 @@ this._itemAdded = { id: aItemId , guid: aGUID , index: aIndex + , dateAdded: aDateAdded , lastModified: aDateAdded }; } @@ -422,11 +429,15 @@ if (aItemType == Ci.nsINavBookmarksService.TYPE_FOLDER) { if (this._itemAdded && this._itemAdded.id == aItemId) { this._itemAdded.lastModified = aLastModified; - } + } if (aItemId in this._livemarks) { if (aProperty == "title") { this._livemarks[aItemId].title = aValue; } + else if (aProperty == "dateAdded") { + this._livemark[aItemId].dateAdded = parseInt(aValue, 10); + } + this._livemarks[aItemId].lastModified = aLastModified; } } @@ -526,8 +537,8 @@ this._nodes = new Map(); this._guid = ""; + this._dateAdded = 0; this._lastModified = 0; - this.loadGroup = null; this.feedURI = null; this.siteURI = null; @@ -539,6 +550,7 @@ this.guid = aLivemarkInfo.guid; this.feedURI = aLivemarkInfo.feedURI; this.siteURI = aLivemarkInfo.siteURI; + this.dateAdded = aLivemarkInfo.dateAdded; this.lastModified = aLivemarkInfo.lastModified; } else { @@ -551,6 +563,10 @@ if (aLivemarkInfo.siteURI) { this.writeSiteURI(aLivemarkInfo.siteURI); } + if (aLivemarkInfo.dateAdded) { + this.dateAdded = aLivemarkInfo.dateAdded; + PlacesUtils.bookmarks.setItemDateAdded(this.id, this.dateAdded); + } // Last modified time must be the last change. if (aLivemarkInfo.lastModified) { this.lastModified = aLivemarkInfo.lastModified; @@ -614,16 +630,13 @@ this.siteURI = aSiteURI; }, - set guid(aGUID) { - this._guid = aGUID; - return aGUID; - }, + set guid(aGUID) this._guid = aGUID, get guid() this._guid, - set lastModified(aLastModified) { - this._lastModified = aLastModified; - return aLastModified; - }, + set dateAdded(aDateAdded) this._dateAdded = aDateAdded, + get dateAdded() this._dateAdded, + + set lastModified(aLastModified) this._lastModified = aLastModified, get lastModified() this._lastModified, /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavBookmarks.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavBookmarks.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavBookmarks.cpp 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavBookmarks.cpp 2014-11-26 21:46:01.000000000 +0000 @@ -19,8 +19,6 @@ #include "GeckoProfiler.h" -#define BOOKMARKS_TO_KEYWORDS_INITIAL_CACHE_LENGTH 32 - using namespace mozilla; // These columns sit to the right of the kGetInfoIndex_* columns. @@ -40,25 +38,6 @@ namespace { -struct keywordSearchData -{ - int64_t itemId; - nsString keyword; -}; - -PLDHashOperator -SearchBookmarkForKeyword(nsTrimInt64HashKey::KeyType aKey, - const nsString aValue, - void* aUserArg) -{ - keywordSearchData* data = reinterpret_cast(aUserArg); - if (data->keyword.Equals(aValue)) { - data->itemId = aKey; - return PL_DHASH_STOP; - } - return PL_DHASH_NEXT; -} - template class AsyncGetBookmarksForURI : public AsyncStatementCallback { @@ -143,8 +122,6 @@ , mCanNotify(false) , mCacheObservers("bookmark-observers") , mBatching(false) - , mBookmarkToKeywordHash(BOOKMARKS_TO_KEYWORDS_INITIAL_CACHE_LENGTH) - , mBookmarkToKeywordHashInitialized(false) { NS_ASSERTION(!gBookmarksService, "Attempting to create two instances of the service!"); @@ -646,7 +623,7 @@ NS_ENSURE_SUCCESS(rv, rv); } - rv = UpdateKeywordsHashForRemovedBookmark(aItemId); + rv = removeOrphanKeywords(); NS_ENSURE_SUCCESS(rv, rv); // A broken url should not interrupt the removal process. @@ -1119,7 +1096,7 @@ NS_ENSURE_SUCCESS(rv, rv); } - rv = UpdateKeywordsHashForRemovedBookmark(child.id); + rv = removeOrphanKeywords(); NS_ENSURE_SUCCESS(rv, rv); } } @@ -2255,39 +2232,23 @@ nsresult -nsNavBookmarks::UpdateKeywordsHashForRemovedBookmark(int64_t aItemId) +nsNavBookmarks::removeOrphanKeywords() { - nsAutoString keyword; - if (NS_SUCCEEDED(GetKeywordForBookmark(aItemId, keyword)) && - !keyword.IsEmpty()) { - nsresult rv = EnsureKeywordsHash(); - NS_ENSURE_SUCCESS(rv, rv); - mBookmarkToKeywordHash.Remove(aItemId); - - // If the keyword is unused, remove it from the database. - keywordSearchData searchData; - searchData.keyword.Assign(keyword); - searchData.itemId = -1; - mBookmarkToKeywordHash.EnumerateRead(SearchBookmarkForKeyword, &searchData); - if (searchData.itemId == -1) { - nsCOMPtr stmt = mDB->GetAsyncStatement( - "DELETE FROM moz_keywords " - "WHERE keyword = :keyword " - "AND NOT EXISTS ( " - "SELECT id " - "FROM moz_bookmarks " - "WHERE keyword_id = moz_keywords.id " - ")" - ); - NS_ENSURE_STATE(stmt); + // If the keyword is unused, remove it from the database. + nsCOMPtr stmt = mDB->GetAsyncStatement( + "DELETE FROM moz_keywords " + "WHERE NOT EXISTS ( " + "SELECT id " + "FROM moz_bookmarks " + "WHERE keyword_id = moz_keywords.id " + ")" + ); + NS_ENSURE_STATE(stmt); + + nsCOMPtr pendingStmt; + nsresult rv = stmt->ExecuteAsync(nullptr, getter_AddRefs(pendingStmt)); + NS_ENSURE_SUCCESS(rv, rv); - rv = stmt->BindStringByName(NS_LITERAL_CSTRING("keyword"), keyword); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr pendingStmt; - rv = stmt->ExecuteAsync(nullptr, getter_AddRefs(pendingStmt)); - NS_ENSURE_SUCCESS(rv, rv); - } - } return NS_OK; } @@ -2303,9 +2264,6 @@ nsresult rv = FetchItemInfo(aBookmarkId, bookmark); NS_ENSURE_SUCCESS(rv, rv); - rv = EnsureKeywordsHash(); - NS_ENSURE_SUCCESS(rv, rv); - // Shortcuts are always lowercased internally. nsAutoString keyword(aUserCasedKeyword); ToLowerCase(keyword); @@ -2331,8 +2289,6 @@ mozStorageStatementScoper updateBookmarkScoper(updateBookmarkStmt); if (keyword.IsEmpty()) { - // Remove keyword association from the hash. - mBookmarkToKeywordHash.Remove(bookmark.id); rv = updateBookmarkStmt->BindNullByName(NS_LITERAL_CSTRING("keyword")); } else { @@ -2350,10 +2306,6 @@ rv = newKeywordStmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); - // Add new keyword association to the hash, removing the old one if needed. - if (!oldKeyword.IsEmpty()) - mBookmarkToKeywordHash.Remove(bookmark.id); - mBookmarkToKeywordHash.Put(bookmark.id, keyword); rv = updateBookmarkStmt->BindStringByName(NS_LITERAL_CSTRING("keyword"), keyword); } NS_ENSURE_SUCCESS(rv, rv); @@ -2411,12 +2363,12 @@ rv = stmt->ExecuteStep(&hasMore); if (NS_FAILED(rv) || !hasMore) { aKeyword.SetIsVoid(true); - return NS_OK; // not found: return void keyword string + return NS_OK; } - // found, get the keyword rv = stmt->GetString(0, aKeyword); NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } @@ -2427,17 +2379,29 @@ NS_ENSURE_ARG_MIN(aBookmarkId, 1); aKeyword.Truncate(0); - nsresult rv = EnsureKeywordsHash(); + nsCOMPtr stmt = mDB->GetStatement( + "/* do not warn (bug no) - there is no index on keyword_id) */ " + "SELECT k.keyword " + "FROM moz_bookmarks b " + "JOIN moz_keywords k ON k.id = b.keyword_id " + "WHERE b.id = :id " + ); + NS_ENSURE_STATE(stmt); + mozStorageStatementScoper scoper(stmt); + + nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), aBookmarkId); NS_ENSURE_SUCCESS(rv, rv); - nsAutoString keyword; - if (!mBookmarkToKeywordHash.Get(aBookmarkId, &keyword)) { + bool hasMore = false; + rv = stmt->ExecuteStep(&hasMore); + if (NS_FAILED(rv) || !hasMore) { aKeyword.SetIsVoid(true); - } - else { - aKeyword.Assign(keyword); + return NS_OK; } + rv = stmt->GetString(0, aKeyword); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } @@ -2454,52 +2418,32 @@ nsAutoString keyword(aUserCasedKeyword); ToLowerCase(keyword); - nsresult rv = EnsureKeywordsHash(); - NS_ENSURE_SUCCESS(rv, rv); - - keywordSearchData searchData; - searchData.keyword.Assign(keyword); - searchData.itemId = -1; - mBookmarkToKeywordHash.EnumerateRead(SearchBookmarkForKeyword, &searchData); - - if (searchData.itemId == -1) { - // Not found. - return NS_OK; - } + nsCOMPtr stmt = mDB->GetStatement( + "/* do not warn (bug no) - there is no index on keyword_id) */ " + "SELECT url FROM moz_keywords k " + "JOIN moz_bookmarks b ON b.keyword_id = k.id " + "JOIN moz_places h ON b.fk = h.id " + "WHERE k.keyword = :keyword " + "ORDER BY b.dateAdded DESC" + ); + NS_ENSURE_STATE(stmt); + mozStorageStatementScoper scoper(stmt); - rv = GetBookmarkURI(searchData.itemId, aURI); + nsresult rv = stmt->BindStringByName(NS_LITERAL_CSTRING("keyword"), keyword); NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - - -nsresult -nsNavBookmarks::EnsureKeywordsHash() { - if (mBookmarkToKeywordHashInitialized) { + bool hasMore = false; + rv = stmt->ExecuteStep(&hasMore); + if (NS_FAILED(rv) || !hasMore) { return NS_OK; } - mBookmarkToKeywordHashInitialized = true; - nsCOMPtr stmt; - nsresult rv = mDB->MainConn()->CreateStatement(NS_LITERAL_CSTRING( - "SELECT b.id, k.keyword " - "FROM moz_bookmarks b " - "JOIN moz_keywords k ON k.id = b.keyword_id " - ), getter_AddRefs(stmt)); + nsCString url; + rv = stmt->GetUTF8String(0, url); NS_ENSURE_SUCCESS(rv, rv); - bool hasMore; - while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) { - int64_t itemId; - rv = stmt->GetInt64(0, &itemId); - NS_ENSURE_SUCCESS(rv, rv); - nsAutoString keyword; - rv = stmt->GetString(1, keyword); - NS_ENSURE_SUCCESS(rv, rv); - - mBookmarkToKeywordHash.Put(itemId, keyword); - } + rv = NS_NewURI(aURI, url); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavBookmarks.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavBookmarks.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavBookmarks.h 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavBookmarks.h 2014-11-26 21:46:01.000000000 +0000 @@ -210,6 +210,11 @@ nsresult GetDescendantFolders(int64_t aFolderId, nsTArray& aDescendantFoldersArray); + static const int32_t kGetChildrenIndex_Guid; + static const int32_t kGetChildrenIndex_Position; + static const int32_t kGetChildrenIndex_Type; + static const int32_t kGetChildrenIndex_PlaceID; + private: static nsNavBookmarks* gBookmarksService; @@ -356,11 +361,6 @@ int64_t RecursiveFindRedirectedBookmark(int64_t aPlaceId); - static const int32_t kGetChildrenIndex_Position; - static const int32_t kGetChildrenIndex_Type; - static const int32_t kGetChildrenIndex_PlaceID; - static const int32_t kGetChildrenIndex_Guid; - class RemoveFolderTransaction MOZ_FINAL : public nsITransaction { public: explicit RemoveFolderTransaction(int64_t aID) : mID(aID) {} @@ -422,20 +422,9 @@ bool mBatching; /** - * Always call EnsureKeywordsHash() and check it for errors before actually - * using the hash. Internal keyword methods are already doing that. - */ - nsresult EnsureKeywordsHash(); - nsDataHashtable mBookmarkToKeywordHash; - bool mBookmarkToKeywordHashInitialized; - - /** - * This function must be called every time a bookmark is removed. - * - * @param aURI - * Uri to test. + * Removes orphan keywords. */ - nsresult UpdateKeywordsHashForRemovedBookmark(int64_t aItemId); + nsresult removeOrphanKeywords(); }; #endif // nsNavBookmarks_h_ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavHistory.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavHistory.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavHistory.cpp 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavHistory.cpp 2014-11-26 21:46:01.000000000 +0000 @@ -1512,7 +1512,8 @@ "SELECT b2.fk, h.url, COALESCE(b2.title, h.title) AS page_title, " "h.rev_host, h.visit_count, h.last_visit_date, f.url, b2.id, " "b2.dateAdded, b2.lastModified, b2.parent, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid, " + "b2.guid, b2.position, b2.type, b2.fk " "FROM moz_bookmarks b2 " "JOIN (SELECT b.fk " "FROM moz_bookmarks b " @@ -1536,7 +1537,8 @@ "SELECT b.fk, h.url, COALESCE(b.title, h.title) AS page_title, " "h.rev_host, h.visit_count, h.last_visit_date, f.url, b.id, " "b.dateAdded, b.lastModified, b.parent, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid," + "b.guid, b.position, b.type, b.fk " "FROM moz_bookmarks b " "JOIN moz_places h ON b.fk = h.id " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " @@ -2237,9 +2239,6 @@ return NS_OK; } - -// nsNavHistory::AddObserver - NS_IMETHODIMP nsNavHistory::AddObserver(nsINavHistoryObserver* aObserver, bool aOwnsWeak) { @@ -2249,9 +2248,6 @@ return mObservers.AppendWeakElement(aObserver, aOwnsWeak); } - -// nsNavHistory::RemoveObserver - NS_IMETHODIMP nsNavHistory::RemoveObserver(nsINavHistoryObserver* aObserver) { @@ -2261,7 +2257,51 @@ return mObservers.RemoveWeakElement(aObserver); } -// nsNavHistory::BeginUpdateBatch +NS_IMETHODIMP +nsNavHistory::GetObservers(uint32_t* _count, + nsINavHistoryObserver*** _observers) +{ + NS_ENSURE_ARG_POINTER(_count); + NS_ENSURE_ARG_POINTER(_observers); + + *_count = 0; + *_observers = nullptr; + + // Clear any cached value, cause it's very likely the consumer has made + // changes to history and is now trying to notify them. + mDaysOfHistory = -1; + + if (!mCanNotify) + return NS_OK; + + nsCOMArray observers; + + // First add the category cache observers. + mCacheObservers.GetEntries(observers); + + // Then add the other observers. + for (uint32_t i = 0; i < mObservers.Length(); ++i) { + const nsCOMPtr &observer = mObservers.ElementAt(i); + // Skip nullified weak observers. + if (observer) + observers.AppendElement(observer); + } + + if (observers.Count() == 0) + return NS_OK; + + *_observers = static_cast + (nsMemory::Alloc(observers.Count() * sizeof(nsINavHistoryObserver*))); + NS_ENSURE_TRUE(*_observers, NS_ERROR_OUT_OF_MEMORY); + + *_count = observers.Count(); + for (uint32_t i = 0; i < *_count; ++i) { + NS_ADDREF((*_observers)[i] = observers[i]); + } + + return NS_OK; +} + // See RunInBatchMode nsresult nsNavHistory::BeginUpdateBatch() @@ -3864,36 +3904,40 @@ } if (IsQueryURI(url)) { - // special case "place:" URIs: turn them into containers + // Special case "place:" URIs: turn them into containers. + nsRefPtr resultNode; + rv = QueryRowToResult(itemId, url, title, accessCount, time, favicon, + getter_AddRefs(resultNode)); + NS_ENSURE_SUCCESS(rv,rv); - // We should never expose the history title for query nodes if the - // bookmark-item's title is set to null (the history title may be the - // query string without the place: prefix). Thus we call getItemTitle - // explicitly. Doing this in the SQL query would be less performant since - // it should be done for all results rather than only for queries. if (itemId != -1) { + rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, + resultNode->mBookmarkGuid); + NS_ENSURE_SUCCESS(rv, rv); + + // We should never expose the history title for query nodes if the + // bookmark-item's title is set to null (the history title may be the + // query string without the place: prefix). Thus we call getItemTitle + // explicitly. Doing this in the SQL query would be less performant since + // it should be done for all results rather than only for queries. nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); - rv = bookmarks->GetItemTitle(itemId, title); + rv = bookmarks->GetItemTitle(itemId, resultNode->mTitle); NS_ENSURE_SUCCESS(rv, rv); } - nsRefPtr resultNode; - rv = QueryRowToResult(itemId, url, title, accessCount, time, favicon, - getter_AddRefs(resultNode)); - NS_ENSURE_SUCCESS(rv,rv); - - if (aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_TAG_QUERY) { + if (itemId != -1 || + aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_TAG_QUERY) { // RESULTS_AS_TAG_QUERY has date columns resultNode->mDateAdded = aRow->AsInt64(kGetInfoIndex_ItemDateAdded); resultNode->mLastModified = aRow->AsInt64(kGetInfoIndex_ItemLastModified); - } - else if (resultNode->IsFolder()) { - // If it's a simple folder node (i.e. a shortcut to another folder), apply - // our options for it. However, if the parent type was tag query, we do not - // apply them, because it would not yield any results. - resultNode->GetAsContainer()->mOptions = aOptions; + if (resultNode->IsFolder()) { + // If it's a simple folder node (i.e. a shortcut to another folder), apply + // our options for it. However, if the parent type was tag query, we do not + // apply them, because it would not yield any results. + resultNode->GetAsContainer()->mOptions = aOptions; + } } resultNode.forget(aResult); @@ -3908,6 +3952,10 @@ resultNode->mFolderId = parentId; resultNode->mDateAdded = aRow->AsInt64(kGetInfoIndex_ItemDateAdded); resultNode->mLastModified = aRow->AsInt64(kGetInfoIndex_ItemLastModified); + + rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, + resultNode->mBookmarkGuid); + NS_ENSURE_SUCCESS(rv, rv); } resultNode->mFrecency = aRow->AsInt32(kGetInfoIndex_Frecency); @@ -4097,7 +4145,8 @@ "SELECT b.fk, h.url, COALESCE(b.title, h.title), " "h.rev_host, h.visit_count, h.last_visit_date, f.url, b.id, " "b.dateAdded, b.lastModified, b.parent, " - ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " + ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid, " + "b.guid, b.position, b.type, b.fk " "FROM moz_bookmarks b " "JOIN moz_places h ON b.fk = h.id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavHistoryResult.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavHistoryResult.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsNavHistoryResult.cpp 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsNavHistoryResult.cpp 2014-11-26 21:46:01.000000000 +0000 @@ -3584,6 +3584,9 @@ node = new nsNavHistorySeparatorResultNode(); NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY); node->mItemId = aItemId; + node->mBookmarkGuid = aGUID; + node->mDateAdded = aDateAdded; + node->mLastModified = aDateAdded; } node->mBookmarkIndex = aIndex; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsPlacesAutoComplete.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsPlacesAutoComplete.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/nsPlacesAutoComplete.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/nsPlacesAutoComplete.js 2014-11-26 21:46:01.000000000 +0000 @@ -12,6 +12,8 @@ "resource://gre/modules/TelemetryStopwatch.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); //////////////////////////////////////////////////////////////////////////////// //// Constants @@ -201,7 +203,6 @@ } } - //////////////////////////////////////////////////////////////////////////////// //// AutoCompleteStatementCallbackWrapper class @@ -497,8 +498,9 @@ this._currentSearchString = fixupSearchText(this._originalSearchString.toLowerCase()); - let searchParamParts = aSearchParam.split(" "); - this._enableActions = searchParamParts.indexOf("enable-actions") != -1; + let params = new Set(aSearchParam.split(" ")); + this._enableActions = params.has("enable-actions"); + this._disablePrivateActions = params.has("disable-private-actions"); this._listener = aListener; let result = Cc["@mozilla.org/autocomplete/simple-result;1"]. @@ -1044,20 +1046,19 @@ let query = this._getSuggestionPrefQuery(); // Bind the needed parameters to the query so consumers can use it. - let (params = query.params) { - params.parent = PlacesUtils.tagsFolderId; - params.query_type = kQueryTypeFiltered; - params.matchBehavior = aMatchBehavior; - params.searchBehavior = this._behavior; - - // We only want to search the tokens that we are left with - not the - // original search string. - params.searchString = aTokens.join(" "); - - // Limit the query to the the maximum number of desired results. - // This way we can avoid doing more work than needed. - params.maxResults = this._maxRichResults; - } + let params = query.params; + params.parent = PlacesUtils.tagsFolderId; + params.query_type = kQueryTypeFiltered; + params.matchBehavior = aMatchBehavior; + params.searchBehavior = this._behavior; + + // We only want to search the tokens that we are left with - not the + // original search string. + params.searchString = aTokens.join(" "); + + // Limit the query to the the maximum number of desired results. + // This way we can avoid doing more work than needed. + params.maxResults = this._maxRichResults; return query; }, @@ -1067,15 +1068,15 @@ let query = this._openPagesQuery; // Bind the needed parameters to the query so consumers can use it. - let (params = query.params) { - params.query_type = kQueryTypeFiltered; - params.matchBehavior = this._matchBehavior; - params.searchBehavior = this._behavior; - // We only want to search the tokens that we are left with - not the - // original search string. - params.searchString = aTokens.join(" "); - params.maxResults = this._maxRichResults; - } + let params = query.params; + params.query_type = kQueryTypeFiltered; + params.matchBehavior = this._matchBehavior; + params.searchBehavior = this._behavior; + + // We only want to search the tokens that we are left with - not the + // original search string. + params.searchString = aTokens.join(" "); + params.maxResults = this._maxRichResults; return query; }, @@ -1104,11 +1105,10 @@ let keyword = aTokens[0]; let query = this._keywordQuery; - let (params = query.params) { - params.keyword = keyword; - params.query_string = queryString; - params.query_type = kQueryTypeKeyword; - } + let params = query.params; + params.keyword = keyword; + params.query_string = queryString; + params.query_type = kQueryTypeKeyword; return query; }, @@ -1126,13 +1126,12 @@ } let query = this._adaptiveQuery; - let (params = query.params) { - params.parent = PlacesUtils.tagsFolderId; - params.search_string = this._currentSearchString; - params.query_type = kQueryTypeFiltered; - params.matchBehavior = aMatchBehavior; - params.searchBehavior = this._behavior; - } + let params = query.params; + params.parent = PlacesUtils.tagsFolderId; + params.search_string = this._currentSearchString; + params.query_type = kQueryTypeFiltered; + params.matchBehavior = aMatchBehavior; + params.searchBehavior = this._behavior; return query; }, @@ -1295,8 +1294,14 @@ */ _hasBehavior: function PAC_hasBehavior(aType) { - return (this._behavior & - Ci.mozIPlacesAutoComplete["BEHAVIOR_" + aType.toUpperCase()]); + let behavior = Ci.mozIPlacesAutoComplete["BEHAVIOR_" + aType.toUpperCase()]; + + if (this._disablePrivateActions && + behavior == Ci.mozIPlacesAutoComplete.BEHAVIOR_OPENPAGE) { + return false; + } + + return this._behavior & behavior; }, /** @@ -1451,74 +1456,76 @@ this._listener = aListener; - // Don't autoFill if the search term is recognized as a keyword, otherwise - // it will override default keywords behavior. Note that keywords are - // hashed on first use, so while the first query may delay a little bit, - // next ones will just hit the memory hash. - if (this._currentSearchString.length == 0 || !this._db || - PlacesUtils.bookmarks.getURIForKeyword(this._currentSearchString)) { - this._finishSearch(); - return; - } + Task.spawn(function* () { + // Don't autoFill if the search term is recognized as a keyword, otherwise + // it will override default keywords behavior. Note that keywords are + // hashed on first use, so while the first query may delay a little bit, + // next ones will just hit the memory hash. + if (this._currentSearchString.length == 0 || !this._db || + (yield PlacesUtils.promiseHrefAndPostDataForKeyword(this._currentSearchString)).href) { + this._finishSearch(); + return; + } - // Don't try to autofill if the search term includes any whitespace. - // This may confuse completeDefaultIndex cause the AUTOCOMPLETE_MATCH - // tokenizer ends up trimming the search string and returning a value - // that doesn't match it, or is even shorter. - if (/\s/.test(this._currentSearchString)) { - this._finishSearch(); - return; - } + // Don't try to autofill if the search term includes any whitespace. + // This may confuse completeDefaultIndex cause the AUTOCOMPLETE_MATCH + // tokenizer ends up trimming the search string and returning a value + // that doesn't match it, or is even shorter. + if (/\s/.test(this._currentSearchString)) { + this._finishSearch(); + return; + } - // Hosts have no "/" in them. - let lastSlashIndex = this._currentSearchString.lastIndexOf("/"); + // Hosts have no "/" in them. + let lastSlashIndex = this._currentSearchString.lastIndexOf("/"); - // Search only URLs if there's a slash in the search string... - if (lastSlashIndex != -1) { - // ...but not if it's exactly at the end of the search string. - if (lastSlashIndex < this._currentSearchString.length - 1) - this._queryURL(); - else - this._finishSearch(); - return; - } + // Search only URLs if there's a slash in the search string... + if (lastSlashIndex != -1) { + // ...but not if it's exactly at the end of the search string. + if (lastSlashIndex < this._currentSearchString.length - 1) + this._queryURL(); + else + this._finishSearch(); + return; + } - // Do a synchronous search on the table of hosts. - let query = this._hostQuery; - query.params.search_string = this._currentSearchString.toLowerCase(); - // This is just to measure the delay to reach the UI, not the query time. - TelemetryStopwatch.start(DOMAIN_QUERY_TELEMETRY); - let ac = this; - let wrapper = new AutoCompleteStatementCallbackWrapper(this, { - handleResult: function (aResultSet) { - let row = aResultSet.getNextRow(); - let trimmedHost = row.getResultByIndex(0); - let untrimmedHost = row.getResultByIndex(1); - // If the untrimmed value doesn't preserve the user's input just - // ignore it and complete to the found host. - if (untrimmedHost && - !untrimmedHost.toLowerCase().contains(ac._originalSearchString.toLowerCase())) { - untrimmedHost = null; - } + // Do a synchronous search on the table of hosts. + let query = this._hostQuery; + query.params.search_string = this._currentSearchString.toLowerCase(); + // This is just to measure the delay to reach the UI, not the query time. + TelemetryStopwatch.start(DOMAIN_QUERY_TELEMETRY); + let ac = this; + let wrapper = new AutoCompleteStatementCallbackWrapper(this, { + handleResult: function (aResultSet) { + let row = aResultSet.getNextRow(); + let trimmedHost = row.getResultByIndex(0); + let untrimmedHost = row.getResultByIndex(1); + // If the untrimmed value doesn't preserve the user's input just + // ignore it and complete to the found host. + if (untrimmedHost && + !untrimmedHost.toLowerCase().contains(ac._originalSearchString.toLowerCase())) { + untrimmedHost = null; + } - ac._result.appendMatch(ac._strippedPrefix + trimmedHost, "", "", "", untrimmedHost); + ac._result.appendMatch(ac._strippedPrefix + trimmedHost, "", "", "", untrimmedHost); - // handleCompletion() will cause the result listener to be called, and - // will display the result in the UI. - }, - - handleError: function (aError) { - Components.utils.reportError( - "URL Inline Complete: An async statement encountered an " + - "error: " + aError.result + ", '" + aError.message + "'"); - }, - - handleCompletion: function (aReason) { - TelemetryStopwatch.finish(DOMAIN_QUERY_TELEMETRY); - ac._finishSearch(); - } - }, this._db); - this._pendingQuery = wrapper.executeAsync([query]); + // handleCompletion() will cause the result listener to be called, and + // will display the result in the UI. + }, + + handleError: function (aError) { + Components.utils.reportError( + "URL Inline Complete: An async statement encountered an " + + "error: " + aError.result + ", '" + aError.message + "'"); + }, + + handleCompletion: function (aReason) { + TelemetryStopwatch.finish(DOMAIN_QUERY_TELEMETRY); + ac._finishSearch(); + } + }, this._db); + this._pendingQuery = wrapper.executeAsync([query]); + }.bind(this)); }, /** @@ -1539,13 +1546,12 @@ // Within the standard autocomplete query, we only search the beginning // of URLs for 1 result. let query = this._urlQuery; - let (params = query.params) { - params.matchBehavior = MATCH_BEGINNING_CASE_SENSITIVE; - params.searchBehavior |= Ci.mozIPlacesAutoComplete.BEHAVIOR_HISTORY | - Ci.mozIPlacesAutoComplete.BEHAVIOR_TYPED | - Ci.mozIPlacesAutoComplete.BEHAVIOR_URL; - params.searchString = this._currentSearchString; - } + let params = query.params; + params.matchBehavior = MATCH_BEGINNING_CASE_SENSITIVE; + params.searchBehavior |= Ci.mozIPlacesAutoComplete.BEHAVIOR_HISTORY | + Ci.mozIPlacesAutoComplete.BEHAVIOR_TYPED | + Ci.mozIPlacesAutoComplete.BEHAVIOR_URL; + params.searchString = this._currentSearchString; // Execute the query. let ac = this; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/PlacesTransactions.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/PlacesTransactions.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/PlacesTransactions.jsm 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/PlacesTransactions.jsm 2014-11-26 21:46:01.000000000 +0000 @@ -67,7 +67,8 @@ * a live bookmark is associated. * - tag - a string. * - tags: an array of strings. - * - guid, parentGuid, newParentGuid: a valid places GUID string. + * - guid, parentGuid, newParentGuid: a valid Places GUID string. + * - guids: an array of valid Places GUID strings. * - title: a string * - index, newIndex: the position of an item in its containing folder, * starting from 0. @@ -463,7 +464,6 @@ get promise() this._promise }; - let TransactionsManager = { // See the documentation at the top of this file. |transact| calls are not // serialized with |batch| calls. @@ -869,6 +869,7 @@ PlacesUtils.bookmarks.DEFAULT_INDEX); DefineTransaction.defineInputProps(["annotation"], DefineTransaction.annotationObjectValidate); +DefineTransaction.defineArrayInputProp("guids", "guid"); DefineTransaction.defineArrayInputProp("urls", "url"); DefineTransaction.defineArrayInputProp("tags", "tag"); DefineTransaction.defineArrayInputProp("annotations", "annotation"); @@ -1269,29 +1270,40 @@ * * Required Input Properties: guid, annotationObject */ -PT.Annotate = DefineTransaction(["guid", "annotations"]); +PT.Annotate = DefineTransaction(["guids", "annotations"]); PT.Annotate.prototype = { - execute: function* (aGuid, aNewAnnos) { - let itemId = yield PlacesUtils.promiseItemId(aGuid); - let currentAnnos = PlacesUtils.getAnnotationsForItem(itemId); - let undoAnnos = []; - for (let newAnno of aNewAnnos) { - let currentAnno = currentAnnos.find( a => a.name == newAnno.name ); - if (!!currentAnno) { - undoAnnos.push(currentAnno); - } - else { - // An unset value removes the annotation. - undoAnnos.push({ name: newAnno.name }); + *execute(aGuids, aNewAnnos) { + let undoAnnosForItem = new Map(); // itemId => undoAnnos; + for (let guid of aGuids) { + let itemId = yield PlacesUtils.promiseItemId(guid); + let currentAnnos = PlacesUtils.getAnnotationsForItem(itemId); + + let undoAnnos = []; + for (let newAnno of aNewAnnos) { + let currentAnno = currentAnnos.find(a => a.name == newAnno.name); + if (!!currentAnno) { + undoAnnos.push(currentAnno); + } + else { + // An unset value removes the annotation. + undoAnnos.push({ name: newAnno.name }); + } } + undoAnnosForItem.set(itemId, undoAnnos); + + PlacesUtils.setAnnotationsForItem(itemId, aNewAnnos); } - PlacesUtils.setAnnotationsForItem(itemId, aNewAnnos); - this.undo = () => { - PlacesUtils.setAnnotationsForItem(itemId, undoAnnos); + this.undo = function() { + for (let [itemId, undoAnnos] of undoAnnosForItem) { + PlacesUtils.setAnnotationsForItem(itemId, undoAnnos); + } }; - this.redo = () => { - PlacesUtils.setAnnotationsForItem(itemId, aNewAnnos); + this.redo = function* () { + for (let guid of aGuids) { + let itemId = yield PlacesUtils.promiseItemId(guid); + PlacesUtils.setAnnotationsForItem(itemId, aNewAnnos); + } }; } }; @@ -1384,28 +1396,61 @@ /** * Transaction for removing an item (any type). * - * Required Input Properties: guid. + * Required Input Properties: guids. */ -PT.Remove = DefineTransaction(["guid"]); +PT.Remove = DefineTransaction(["guids"]); PT.Remove.prototype = { - execute: function* (aGuid) { - const bms = PlacesUtils.bookmarks; - - let itemInfo = null; - try { - itemInfo = yield PlacesUtils.promiseBookmarksTree(aGuid); + *execute(aGuids) { + function promiseBookmarksTree(guid) { + try { + return PlacesUtils.promiseBookmarksTree(guid); + } + catch(ex) { + throw new Error("Failed to get info for the specified item (guid: " + + guid + "). Ex: " + ex); + } } - catch(ex) { - throw new Error("Failed to get info for the specified item (guid: " + - aGuid + "). Ex: " + ex); + let toRestore = [for (guid of aGuids) yield promiseBookmarksTree(guid)]; + + let removeThem = Task.async(function* () { + for (let guid of aGuids) { + PlacesUtils.bookmarks.removeItem(yield PlacesUtils.promiseItemId(guid)); + } + }); + yield removeThem(); + + this.undo = Task.async(function* () { + for (let info of toRestore) { + yield createItemsFromBookmarksTree(info, true); + } + }); + this.redo = removeThem; + } +}; + +/** + * Transactions for removing all bookmarks for one or more urls. + * + * Required Input Properties: urls. + */ +PT.RemoveBookmarksForUrls = DefineTransaction(["urls"]); +PT.RemoveBookmarksForUrls.prototype = { + *execute(aUrls) { + let guids = []; + for (let url of aUrls) { + yield PlacesUtils.bookmarks.fetch({ url }, info => { + guids.push(info.guid); + }); } - PlacesUtils.bookmarks.removeItem(yield PlacesUtils.promiseItemId(aGuid)); - this.undo = createItemsFromBookmarksTree.bind(null, itemInfo, true); + let removeTxn = TransactionsHistory.getRawTransaction(PT.Remove(guids)); + yield removeTxn.execute(); + this.undo = removeTxn.undo.bind(removeTxn); + this.redo = removeTxn.redo.bind(removeTxn); } }; /** - * Transaction for tagging a URI. + * Transaction for tagging urls. * * Required Input Properties: urls, tags. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/PlacesUtils.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/PlacesUtils.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/PlacesUtils.jsm 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/PlacesUtils.jsm 2014-11-26 21:46:01.000000000 +0000 @@ -835,6 +835,17 @@ }, /** + * Gets the href and the post data for a given keyword, if any. + * + * @param keyword + * The string keyword to look for. + * @return {Promise} + * @resolves to a { href, postData } object. Both properties evaluate to null + * if no keyword is found. + */ + promiseHrefAndPostDataForKeyword(keyword) KeywordsCache.promiseEntry(keyword), + + /** * Get the URI (and any associated POST data) for a given keyword. * @param aKeyword string keyword * @returns an array containing a string URL and a string of POST data @@ -1965,6 +1976,114 @@ } }; +// Cache of bookmarks keywords, used to quickly resolve keyword => URL requests. +let KeywordsCache = { + /** + * Initializes the cache. + * Every method should check _initialized and, if false, yield _initialize(). + */ + _initialized: false, + _initialize: Task.async(function* () { + // First populate the cache... + yield this._reloadCache(); + + // ...then observe changes to keep the cache up-to-date. + PlacesUtils.bookmarks.addObserver(this, false); + PlacesUtils.registerShutdownFunction(() => { + PlacesUtils.bookmarks.removeObserver(this); + }); + + this._initialized = true; + }), + + // nsINavBookmarkObserver + // Manually updating the cache would be tricky because some notifications + // don't report the original bookmark url and we also keep urls sorted by + // last modified. Since changing a keyword-ed bookmark is a rare event, + // it's easier to reload the cache. + onItemChanged(itemId, property, isAnno, val, lastModified, type, + parentId, guid, parentGuid) { + if (property == "keyword" || property == this.POST_DATA_ANNO || + this._keywordedGuids.has(guid)) { + // Since this cache is used in hot paths, it should be readily available + // as fast as possible. + this._reloadCache().catch(Cu.reportError); + } + }, + onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid) { + if (this._keywordedGuids.has(guid)) { + // Since this cache is used in hot paths, it should be readily available + // as fast as possible. + this._reloadCache().catch(Cu.reportError); + } + }, + QueryInterface: XPCOMUtils.generateQI([ Ci.nsINavBookmarkObserver ]), + __noSuchMethod__() {}, // Catch all remaining onItem* methods. + + // Maps an { href, postData } object to each keyword. + // Even if a keyword may be associated to multiple URLs, only the last + // modified bookmark href is retained here. + _urlDataForKeyword: null, + // Tracks GUIDs having a keyword. + _keywordedGuids: null, + + /** + * Reloads the cache. + */ + _reloadPromise: null, + _reloadCache() { + return this._reloadPromise = Task.spawn(function* () { + let db = yield PlacesUtils.promiseDBConnection(); + let rows = yield db.execute( + `/* do not warn (bug no) - there is no index on keyword_id */ + SELECT b.id, b.guid, h.url, k.keyword FROM moz_bookmarks b + JOIN moz_places h ON h.id = b.fk + JOIN moz_keywords k ON k.id = b.keyword_id + ORDER BY b.lastModified DESC + `); + + this._urlDataForKeyword = new Map(); + this._keywordedGuids = new Set(); + + for (let row of rows) { + let guid = row.getResultByName("guid"); + this._keywordedGuids.add(guid); + + let keyword = row.getResultByName("keyword"); + // Only keep the most recent href. + let urlData = this._urlDataForKeyword.get(keyword); + if (urlData) + continue; + + let id = row.getResultByName("id"); + let href = row.getResultByName("url"); + let postData = PlacesUtils.getPostDataForBookmark(id); + this._urlDataForKeyword.set(keyword, { href, postData }); + } + }.bind(this)).then(() => { + this._reloadPromise = null; + }); + }, + + /** + * Fetches a { href, postData } entry for the given keyword. + * + * @param keyword + * The keyword to look for. + * @return {promise} + * @resolves when the fetching is complete. + */ + promiseEntry: Task.async(function* (keyword) { + // We could yield regardless and do the checks internally, but that would + // waste at least a couple ticks and this can be used on hot paths. + if (!this._initialized) + yield this._initialize(); + if (this._reloadPromise) + yield this._reloadPromise; + return this._urlDataForKeyword.get(keyword) || { href: null, postData: null }; + }), +}; + //////////////////////////////////////////////////////////////////////////////// //// Transactions handlers. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_fetch.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_fetch.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_fetch.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_fetch.js 2014-11-26 21:46:01.000000000 +0000 @@ -255,6 +255,9 @@ title: "a bookmark" }); checkBookmarkObject(bm1); + // Also ensure that fecth-by-url excludes the tags folder. + PlacesUtils.tagging.tagURI(uri(bm1.url.href), ["Test Tag"]); + let bm2 = yield PlacesUtils.bookmarks.fetch({ url: bm1.url }, gAccumulator.callback); checkBookmarkObject(bm2); @@ -293,6 +296,9 @@ Assert.equal(gAccumulator.results.length, 2); gAccumulator.results.forEach(checkBookmarkObject); Assert.deepEqual(gAccumulator.results[0], bm5); + + // cleanup + PlacesUtils.tagging.untagURI(uri(bm1.url.href), ["Test Tag"]); }); add_task(function* fetch_bykeyword_nonexisting() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js 2014-11-26 21:46:01.000000000 +0000 @@ -111,10 +111,6 @@ tag.url, null, tag.dateAdded, tag.guid, tag.parentGuid ] }, { name: "onItemChanged", - arguments: [ tagId, "tags", false, "", - tag.lastModified, tag.type, tagParentId, - tag.guid, tag.parentGuid ] }, - { name: "onItemChanged", arguments: [ itemId, "tags", false, "", bm.lastModified, bm.type, parentId, bm.guid, bm.parentGuid ] } @@ -188,6 +184,65 @@ bm.parentGuid ] } ]); }); + +add_task(function* update_move_same_folder() { + // Ensure there are at least two items in place (others test do so for us, + // but we don't have to depend on that). + let sep = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR, + parentGuid: PlacesUtils.bookmarks.unfiledGuid }); + let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: new URL("http://move.example.com/") }); + let bmItemId = yield PlacesUtils.promiseItemId(bm.guid); + let bmParentId = yield PlacesUtils.promiseItemId(bm.parentGuid); + let bmOldIndex = bm.index; + + let observer = expectNotifications(); + bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + index: 0 }); + Assert.equal(bm.index, 0); + observer.check([ { name: "onItemMoved", + arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index, + bm.type, bm.guid, bm.parentGuid, bm.parentGuid ] } + ]); + + // Test that we get the right index for DEFAULT_INDEX input. + bmOldIndex = 0; + observer = expectNotifications(); + bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + index: PlacesUtils.bookmarks.DEFAULT_INDEX }); + Assert.ok(bm.index > 0); + observer.check([ { name: "onItemMoved", + arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index, + bm.type, bm.guid, bm.parentGuid, bm.parentGuid ] } + ]); +}); + +add_task(function* update_move_different_folder() { + let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: new URL("http://move.example.com/") }); + let folder = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER, + parentGuid: PlacesUtils.bookmarks.unfiledGuid }); + let bmItemId = yield PlacesUtils.promiseItemId(bm.guid); + let bmOldParentId = PlacesUtils.unfiledBookmarksFolderId; + let bmOldIndex = bm.index; + + let observer = expectNotifications(); + bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid, + parentGuid: folder.guid, + index: PlacesUtils.bookmarks.DEFAULT_INDEX }); + Assert.equal(bm.index, 0); + let bmNewParentId = yield PlacesUtils.promiseItemId(folder.guid); + observer.check([ { name: "onItemMoved", + arguments: [ bmItemId, bmOldParentId, bmOldIndex, bmNewParentId, + bm.index, bm.type, bm.guid, + PlacesUtils.bookmarks.unfiledGuid, + bm.parentGuid ] } + ]); +}); add_task(function* remove_bookmark() { let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_update.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_update.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_update.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/bookmarks/test_bookmarks_update.js 2014-11-26 21:46:01.000000000 +0000 @@ -402,6 +402,71 @@ Assert.equal(descendant.index, 1); }); +add_task(function* update_move_append() { + let folder_a = + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, + type: PlacesUtils.bookmarks.TYPE_FOLDER }); + checkBookmarkObject(folder_a); + let folder_b = + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, + type: PlacesUtils.bookmarks.TYPE_FOLDER }); + checkBookmarkObject(folder_b); + + /* folder_a: [sep_1, sep_2, sep_3], folder_b: [] */ + let sep_1 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder_a.guid, + type: PlacesUtils.bookmarks.TYPE_SEPARATOR }); + checkBookmarkObject(sep_1); + let sep_2 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder_a.guid, + type: PlacesUtils.bookmarks.TYPE_SEPARATOR }); + checkBookmarkObject(sep_2); + let sep_3 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder_a.guid, + type: PlacesUtils.bookmarks.TYPE_SEPARATOR }); + checkBookmarkObject(sep_3); + + function ensurePosition(info, parentGuid, index) { + checkBookmarkObject(info); + Assert.equal(info.parentGuid, parentGuid); + Assert.equal(info.index, index); + } + + // folder_a: [sep_2, sep_3, sep_1], folder_b: [] + sep_1.index = PlacesUtils.bookmarks.DEFAULT_INDEX; + // Note sep_1 includes parentGuid even though we're not moving the item to + // another folder + sep_1 = yield PlacesUtils.bookmarks.update(sep_1); + ensurePosition(sep_1, folder_a.guid, 2); + sep_2 = yield PlacesUtils.bookmarks.fetch(sep_2.guid); + ensurePosition(sep_2, folder_a.guid, 0); + sep_3 = yield PlacesUtils.bookmarks.fetch(sep_3.guid); + ensurePosition(sep_3, folder_a.guid, 1); + sep_1 = yield PlacesUtils.bookmarks.fetch(sep_1.guid); + ensurePosition(sep_1, folder_a.guid, 2); + + // folder_a: [sep_2, sep_1], folder_b: [sep_3] + sep_3.index = PlacesUtils.bookmarks.DEFAULT_INDEX; + sep_3.parentGuid = folder_b.guid; + sep_3 = yield PlacesUtils.bookmarks.update(sep_3); + ensurePosition(sep_3, folder_b.guid, 0); + sep_2 = yield PlacesUtils.bookmarks.fetch(sep_2.guid); + ensurePosition(sep_2, folder_a.guid, 0); + sep_1 = yield PlacesUtils.bookmarks.fetch(sep_1.guid); + ensurePosition(sep_1, folder_a.guid, 1); + sep_3 = yield PlacesUtils.bookmarks.fetch(sep_3.guid); + ensurePosition(sep_3, folder_b.guid, 0); + + // folder_a: [sep_1], folder_b: [sep_3, sep_2] + sep_2.index = Number.MAX_SAFE_INTEGER; + sep_2.parentGuid = folder_b.guid; + sep_2 = yield PlacesUtils.bookmarks.update(sep_2); + ensurePosition(sep_2, folder_b.guid, 1); + sep_1 = yield PlacesUtils.bookmarks.fetch(sep_1.guid); + ensurePosition(sep_1, folder_a.guid, 0); + sep_3 = yield PlacesUtils.bookmarks.fetch(sep_3.guid); + ensurePosition(sep_3, folder_b.guid, 0); + sep_2 = yield PlacesUtils.bookmarks.fetch(sep_2.guid); + ensurePosition(sep_2, folder_b.guid, 1); +}); + function run_test() { run_next_test(); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/browser/browser_bug248970.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/browser/browser_bug248970.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/browser/browser_bug248970.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/browser/browser_bug248970.js 2014-11-26 21:46:01.000000000 +0000 @@ -29,10 +29,6 @@ yield promiseClearHistory(); - // History database should be empty - is(PlacesUtils.history.hasHistoryEntries, false, - "History database should be empty"); - // Ensure we wait for the default bookmarks import. let bookmarksDeferred = Promise.defer(); waitForCondition(() => { @@ -53,10 +49,6 @@ { uri: visitedURIs[7], transition: TRANSITION_DOWNLOAD } ]); - // History database should have entries - is(PlacesUtils.history.hasHistoryEntries, true, - "History database should have entries"); - placeItemsCount += 7; // We added 7 new items to history. is(getPlacesItemsCount(), placeItemsCount, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/history/head_history.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/history/head_history.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/history/head_history.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/history/head_history.js 2014-11-26 21:46:01.000000000 +0000 @@ -0,0 +1,19 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* 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/. */ + +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +}; + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/history/test_remove.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/history/test_remove.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/history/test_remove.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/history/test_remove.js 2014-11-26 21:46:01.000000000 +0000 @@ -0,0 +1,342 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* 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/. */ + +// Tests for `History.remove`, as implemented in History.jsm + +"use strict"; + +Cu.importGlobalProperties(["URL"]); + + +// Test removing a single page +add_task(function* test_remove_single() { + let WITNESS_URI = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove/" + Math.random()); + yield promiseAddVisits(WITNESS_URI); + Assert.ok(page_in_database(WITNESS_URI)); + + let remover = Task.async(function*(name, filter, options) { + do_print(name); + do_print(JSON.stringify(options)); + do_print("Setting up visit"); + + let uri = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove/" + Math.random()); + let title = "Visit " + Math.random(); + yield promiseAddVisits({uri: uri, title: title}); + Assert.ok(visits_in_database(uri), "History entry created"); + + let removeArg = yield filter(uri); + + if (options.addBookmark) { + PlacesUtils.bookmarks.insertBookmark( + PlacesUtils.unfiledBookmarksFolderId, + uri, + PlacesUtils.bookmarks.DEFAULT_INDEX, + "test bookmark"); + } + + let shouldRemove = !options.addBookmark; + let observer; + let promiseObserved = new Promise((resolve, reject) => { + observer = { + onBeginUpdateBatch: function() {}, + onEndUpdateBatch: function() {}, + onVisit: function(uri) { + reject(new Error("Unexpected call to onVisit " + uri.spec)); + }, + onTitleChanged: function(uri) { + reject(new Error("Unexpected call to onTitleChanged " + uri.spec)); + }, + onClearHistory: function() { + reject("Unexpected call to onClearHistory"); + }, + onPageChanged: function(uri) { + reject(new Error("Unexpected call to onPageChanged " + uri.spec)); + }, + onFrecencyChanged: function(aURI) { + try { + Assert.ok(!shouldRemove, "Observing onFrecencyChanged"); + Assert.equal(aURI.spec, uri.spec, "Observing effect on the right uri"); + } finally { + resolve(); + } + }, + onManyFrecenciesChanged: function() { + try { + Assert.ok(!shouldRemove, "Observing onManyFrecenciesChanged"); + } finally { + resolve(); + } + }, + onDeleteURI: function(aURI) { + try { + Assert.ok(shouldRemove, "Observing onDeleteURI"); + Assert.equal(aURI.spec, uri.spec, "Observing effect on the right uri"); + } finally { + resolve(); + } + }, + onDeleteVisits: function(aURI) { + Assert.equal(aURI.spec, uri.spec, "Observing onDeleteVisits on the right uri"); + } + }; + }); + PlacesUtils.history.addObserver(observer, false); + + do_print("Performing removal"); + let removed = false; + if (options.useCallback) { + let onRowCalled = false; + removed = yield PlacesUtils.history.remove(removeArg, page => { + Assert.equal(onRowCalled, false, "Callback has not been called yet"); + onRowCalled = true; + Assert.equal(page.url.href, uri.spec, "Callback provides the correct url"); + Assert.equal(page.guid, do_get_guid_for_uri(uri), "Callback provides the correct guid"); + Assert.equal(page.title, title, "Callback provides the correct title"); + Assert.equal(page.frecency, frecencyForUrl(uri), "Callback provides the correct frecency"); + }); + Assert.ok(onRowCalled, "Callback has been called"); + } else { + removed = yield PlacesUtils.history.remove(removeArg); + } + + yield promiseObserved; + PlacesUtils.history.removeObserver(observer); + + Assert.equal(visits_in_database(uri), 0, "History entry has disappeared"); + Assert.notEqual(visits_in_database(WITNESS_URI), 0, "Witness URI still has visits"); + Assert.notEqual(page_in_database(WITNESS_URI), 0, "Witness URI is still here"); + if (shouldRemove) { + Assert.ok(removed, "Something was removed"); + Assert.equal(page_in_database(uri), 0, "Page has disappeared"); + } else { + Assert.ok(!removed, "The page was not removed, as there was a bookmark"); + Assert.notEqual(page_in_database(uri), 0, "The page is still present"); + } + }); + + try { + for (let useCallback of [false, true]) { + for (let addBookmark of [false, true]) { + let options = { useCallback: useCallback, addBookmark: addBookmark }; + yield remover("Testing History.remove() with a single URI", x => x, options); + yield remover("Testing History.remove() with a single string url", x => x.spec, options); + yield remover("Testing History.remove() with a single string guid", x => do_get_guid_for_uri(x), options); + yield remover("Testing History.remove() with a single URI in an array", x => [x], options); + yield remover("Testing History.remove() with a single string url in an array", x => [x.spec], options); + yield remover("Testing History.remove() with a single string guid in an array", x => [do_get_guid_for_uri(x)], options); + } + } + } finally { + yield promiseClearHistory(); + } + return; +}); + +// Test removing a list of pages +add_task(function* test_remove_many() { + const SIZE = 10; + + do_print("Adding a witness page"); + let WITNESS_URI = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove/" + Math.random());; + yield promiseAddVisits(WITNESS_URI); + Assert.ok(page_in_database(WITNESS_URI), "Witness page added"); + + do_print("Generating samples"); + let pages = []; + for (let i = 0; i < SIZE; ++i) { + let uri = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove?sample=" + i + "&salt=" + Math.random()); + let title = "Visit " + i + ", " + Math.random(); + let hasBookmark = i % 3 == 0; + let resolve; + let page = { + uri: uri, + title: title, + hasBookmark: hasBookmark, + // `true` once `onResult` has been called for this page + onResultCalled: false, + // `true` once `onDeleteVisits` has been called for this page + onDeleteVisitsCalled: false, + // `true` once `onFrecencyChangedCalled` has been called for this page + onFrecencyChangedCalled: false, + // `true` once `onDeleteURI` has been called for this page + onDeleteURICalled: false, + }; + do_print("Pushing: " + uri.spec); + pages.push(page); + + yield promiseAddVisits(page); + page.guid = do_get_guid_for_uri(uri); + if (hasBookmark) { + PlacesUtils.bookmarks.insertBookmark( + PlacesUtils.unfiledBookmarksFolderId, + uri, + PlacesUtils.bookmarks.DEFAULT_INDEX, + "test bookmark " + i); + } + Assert.ok(page_in_database(uri), "Page added"); + } + + do_print("Mixing key types and introducing dangling keys"); + let keys = []; + for (let i = 0; i < SIZE; ++i) { + if (i % 4 == 0) { + keys.push(pages[i].uri); + keys.push(NetUtil.newURI("http://example.org/dangling/nsIURI/" + i)); + } else if (i % 4 == 1) { + keys.push(new URL(pages[i].uri.spec)); + keys.push(new URL("http://example.org/dangling/URL/" + i)); + } else if (i % 4 == 2) { + keys.push(pages[i].uri.spec); + keys.push("http://example.org/dangling/stringuri/" + i); + } else { + keys.push(pages[i].guid); + keys.push(("guid_" + i + "_01234567890").substr(0, 12)); + } + } + + let observer = { + onBeginUpdateBatch: function() {}, + onEndUpdateBatch: function() {}, + onVisit: function(aURI) { + Assert.ok(false, "Unexpected call to onVisit " + aURI.spec); + }, + onTitleChanged: function(aURI) { + Assert.ok(false, "Unexpected call to onTitleChanged " + aURI.spec); + }, + onClearHistory: function() { + Assert.ok(false, "Unexpected call to onClearHistory"); + }, + onPageChanged: function(aURI) { + Assert.ok(false, "Unexpected call to onPageChanged " + aURI.spec); + }, + onFrecencyChanged: function(aURI) { + let origin = pages.find(x => x.uri.spec == aURI.spec); + Assert.ok(origin); + Assert.ok(origin.hasBookmark, "Observing onFrecencyChanged on a page with a bookmark"); + origin.onFrecencyChangedCalled = true; + // We do not make sure that `origin.onFrecencyChangedCalled` is `false`, as + }, + onManyFrecenciesChanged: function() { + Assert.ok(false, "Observing onManyFrecenciesChanges, this is most likely correct but not covered by this test"); + }, + onDeleteURI: function(aURI) { + let origin = pages.find(x => x.uri.spec == aURI.spec); + Assert.ok(origin); + Assert.ok(!origin.hasBookmark, "Observing onDeleteURI on a page without a bookmark"); + Assert.ok(!origin.onDeleteURICalled, "Observing onDeleteURI for the first time"); + origin.onDeleteURICalled = true; + }, + onDeleteVisits: function(aURI) { + let origin = pages.find(x => x.uri.spec == aURI.spec); + Assert.ok(origin); + Assert.ok(!origin.onDeleteVisitsCalled, "Observing onDeleteVisits for the first time"); + origin.onDeleteVisitsCalled = true; + } + }; + PlacesUtils.history.addObserver(observer, false); + + do_print("Removing the pages and checking the callbacks"); + let removed = yield PlacesUtils.history.remove(keys, page => { + let origin = pages.find(candidate => candidate.uri.spec == page.url.href); + + Assert.ok(origin, "onResult has a valid page"); + Assert.ok(!origin.onResultCalled, "onResult has not seen this page yet"); + origin.onResultCalled = true; + Assert.equal(page.guid, origin.guid, "onResult has the right guid"); + Assert.equal(page.title, origin.title, "onResult has the right title"); + }); + Assert.ok(removed, "Something was removed"); + + PlacesUtils.history.removeObserver(observer); + + do_print("Checking out results"); + // By now the observers should have been called. + for (let i = 0; i < pages.length; ++i) { + let page = pages[i]; + do_print("Page: " + i); + Assert.ok(page.onResultCalled, "We have reached the page from the callback"); + Assert.ok(visits_in_database(page.uri) == 0, "History entry has disappeared"); + Assert.equal(page_in_database(page.uri) != 0, page.hasBookmark, "Page is present only if it also has bookmarks"); + Assert.equal(page.onFrecencyChangedCalled, page.onDeleteVisitsCalled, "onDeleteVisits was called iff onFrecencyChanged was called"); + Assert.ok(page.onFrecencyChangedCalled ^ page.onDeleteURICalled, "Either onFrecencyChanged or onDeleteURI was called"); + } + + Assert.notEqual(visits_in_database(WITNESS_URI), 0, "Witness URI still has visits"); + Assert.notEqual(page_in_database(WITNESS_URI), 0, "Witness URI is still here"); + + do_print("Cleaning up"); + yield promiseClearHistory(); + +}); + +// Test the various error cases +add_task(function* test_error_cases() { + Assert.throws( + () => PlacesUtils.history.remove(), + /TypeError: Invalid url/, + "History.remove with no argument should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove(null), + /TypeError: Invalid url/, + "History.remove with `null` should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove(undefined), + /TypeError: Invalid url/, + "History.remove with `undefined` should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove("not a guid, obviously"), + /TypeError: .* is not a valid URL/, + "History.remove with an ill-formed guid/url argument should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove({"not the kind of object we know how to handle": true}), + /TypeError: Invalid url/, + "History.remove with an unexpected object should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove([]), + /TypeError: Expected at least one page/, + "History.remove with an empty array should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove([null]), + /TypeError: Invalid url or guid/, + "History.remove with an array containing null should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove(["http://example.org", "not a guid, obviously"]), + /TypeError: .* is not a valid URL/, + "History.remove with an array containing an ill-formed guid/url argument should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove(["0123456789ab"/*valid guid*/, null]), + /TypeError: Invalid url or guid: null/, + "History.remove with an array containing a guid and a second argument that is null should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove(["http://example.org", {"not the kind of object we know how to handle": true}]), + /TypeError: Invalid url/, + "History.remove with an array containing an unexpected objecgt should throw a TypeError" + ); + Assert.throws( + () => PlacesUtils.history.remove("http://example.org", "not a function, obviously"), + /TypeError: Invalid function/, + "History.remove with a second argument that is not a function argument should throw a TypeError" + ); + try { + PlacesUtils.history.remove("http://example.org/I/have/clearly/not/been/added", null); + Assert.ok(true, "History.remove should ignore `null` as a second argument"); + } catch (ex) { + Assert.ok(false, "History.remove should ignore `null` as a second argument"); + } +}); + +function run_test() { + run_next_test(); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/history/xpcshell.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/history/xpcshell.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/history/xpcshell.ini 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/history/xpcshell.ini 2014-11-26 21:46:01.000000000 +0000 @@ -0,0 +1,5 @@ +[DEFAULT] +head = head_history.js +tail = + +[test_remove.js] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/moz.build 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/moz.build 2014-11-26 21:46:01.000000000 +0000 @@ -6,17 +6,21 @@ TEST_DIRS += ['cpp'] +TESTING_JS_MODULES += [ + 'PlacesTestUtils.jsm', +] + XPCSHELL_TESTS_MANIFESTS += [ 'autocomplete/xpcshell.ini', 'bookmarks/xpcshell.ini', 'expiration/xpcshell.ini', 'favicons/xpcshell.ini', + 'history/xpcshell.ini', 'inline/xpcshell.ini', 'migration/xpcshell.ini', 'network/xpcshell.ini', 'queries/xpcshell.ini', 'unifiedcomplete/xpcshell.ini', - 'unit/history/xpcshell.ini', 'unit/xpcshell.ini', 'xpcshell.ini', ] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/PlacesTestUtils.jsm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/PlacesTestUtils.jsm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/PlacesTestUtils.jsm 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/PlacesTestUtils.jsm 2014-11-26 21:46:01.000000000 +0000 @@ -0,0 +1,76 @@ +"use strict"; + +this.EXPORTED_SYMBOLS = [ + "PlacesTestUtils", +]; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", + "resource://gre/modules/PlacesUtils.jsm"); + + +this.PlacesTestUtils = Object.freeze({ + /** + * Asynchronously adds visits to a page. + * + * @param aPlaceInfo + * Can be an nsIURI, in such a case a single LINK visit will be added. + * Otherwise can be an object describing the visit to add, or an array + * of these objects: + * { uri: nsIURI of the page, + * [optional] transition: one of the TRANSITION_* from nsINavHistoryService, + * [optional] title: title of the page, + * [optional] visitDate: visit date in microseconds from the epoch + * [optional] referrer: nsIURI of the referrer for this visit + * } + * + * @return {Promise} + * @resolves When all visits have been added successfully. + * @rejects JavaScript exception. + */ + addVisits(placeInfo) { + return new Promise((resolve, reject) => { + let places = []; + if (placeInfo instanceof Ci.nsIURI) { + places.push({ uri: placeInfo }); + } + else if (Array.isArray(placeInfo)) { + places = places.concat(placeInfo); + } else { + places.push(placeInfo) + } + + // Create mozIVisitInfo for each entry. + let now = Date.now(); + for (let place of places) { + if (typeof place.title != "string") { + place.title = "test visit for " + place.uri.spec; + } + place.visits = [{ + transitionType: place.transition === undefined ? Ci.nsINavHistoryService.TRANSITION_LINK + : place.transition, + visitDate: place.visitDate || (now++) * 1000, + referrerURI: place.referrer + }]; + } + + PlacesUtils.asyncHistory.updatePlaces( + places, + { + handleError: function AAV_handleError(resultCode, placeInfo) { + let ex = new Components.Exception("Unexpected error in adding visits.", + resultCode); + reject(ex); + }, + handleResult: function () {}, + handleCompletion: function UP_handleCompletion() { + resolve(); + } + } + ); + }); + }, +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js 2014-11-26 21:46:01.000000000 +0000 @@ -31,6 +31,7 @@ }); add_task(function* test_searchEngine_autofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("CakeSearch", "", "", "", "GET", "http://cake.search/"); let engine = Services.search.getEngineByName("CakeSearch"); @@ -48,6 +49,7 @@ }); add_task(function* test_searchEngine_prefix_space_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("CupcakeSearch", "", "", "", "GET", "http://cupcake.search/"); let engine = Services.search.getEngineByName("CupcakeSearch"); @@ -65,6 +67,7 @@ }); add_task(function* test_searchEngine_trailing_space_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("BaconSearch", "", "", "", "GET", "http://bacon.search/"); let engine = Services.search.getEngineByName("BaconSearch"); @@ -82,6 +85,7 @@ }); add_task(function* test_searchEngine_www_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("HamSearch", "", "", "", "GET", "http://ham.search/"); let engine = Services.search.getEngineByName("HamSearch"); @@ -99,6 +103,7 @@ }); add_task(function* test_searchEngine_different_scheme_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("PieSearch", "", "", "", "GET", "https://pie.search/"); let engine = Services.search.getEngineByName("PieSearch"); @@ -116,6 +121,7 @@ }); add_task(function* test_searchEngine_matching_prefix_autofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("BeanSearch", "", "", "", "GET", "http://www.bean.search/"); let engine = Services.search.getEngineByName("BeanSearch"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_searchEngine_host.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_searchEngine_host.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_searchEngine_host.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_searchEngine_host.js 2014-11-26 21:46:01.000000000 +0000 @@ -38,6 +38,7 @@ add_task(function* test_searchEngine_autoFill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); Services.search.addEngineWithDetails("MySearchEngine", "", "", "", "GET", "http://my.search.com/"); let engine = Services.search.getEngineByName("MySearchEngine"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js 2014-11-26 21:46:01.000000000 +0000 @@ -40,6 +40,7 @@ // Disable autoFill to avoid handling the first result. Services.prefs.setBoolPref("browser.urlbar.autoFill", "false"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false); do_log_info("http://www.site matches all site"); yield check_autocomplete({ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_tabmatches.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_tabmatches.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unifiedcomplete/test_tabmatches.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unifiedcomplete/test_tabmatches.js 2014-11-26 21:46:01.000000000 +0000 @@ -60,6 +60,23 @@ { uri: makeActionURI("switchtab", {url: "http://xyz.net/"}), title: "xyz.net - we're better than ABC", style: [ "action", "switchtab" ] } ] }); + do_log_info("three results, no tab matches (disable-private-actions)"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions disable-private-actions", + matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc", searchQuery: "abc"}), title: "MozSearch", style: [ "action", "searchengine" ] }, + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + }); + + do_log_info("two results (actions disabled)"); + yield check_autocomplete({ + search: "abc", + searchParam: "", + matches: [ { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + }); + do_log_info("three results, no tab matches"); removeOpenPages(uri1, 1); removeOpenPages(uri2, 6); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/history/head_history.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/history/head_history.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/history/head_history.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/history/head_history.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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/. */ - -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cr = Components.results; -const Cu = Components.utils; - -Cu.import("resource://gre/modules/Services.jsm"); - -// Import common head. -let (commonFile = do_get_file("../../head_common.js", false)) { - let uri = Services.io.newFileURI(commonFile); - Services.scriptloader.loadSubScript(uri.spec, this); -}; - diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/history/test_remove.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/history/test_remove.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/history/test_remove.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/history/test_remove.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,342 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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/. */ - -// Tests for `History.remove`, as implemented in History.jsm - -"use strict"; - -Cu.importGlobalProperties(["URL"]); - - -// Test removing a single page -add_task(function* test_remove_single() { - let WITNESS_URI = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove/" + Math.random()); - yield promiseAddVisits(WITNESS_URI); - Assert.ok(page_in_database(WITNESS_URI)); - - let remover = Task.async(function*(name, filter, options) { - do_print(name); - do_print(JSON.stringify(options)); - do_print("Setting up visit"); - - let uri = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove/" + Math.random()); - let title = "Visit " + Math.random(); - yield promiseAddVisits({uri: uri, title: title}); - Assert.ok(visits_in_database(uri), "History entry created"); - - let removeArg = yield filter(uri); - - if (options.addBookmark) { - PlacesUtils.bookmarks.insertBookmark( - PlacesUtils.unfiledBookmarksFolderId, - uri, - PlacesUtils.bookmarks.DEFAULT_INDEX, - "test bookmark"); - } - - let shouldRemove = !options.addBookmark; - let observer; - let promiseObserved = new Promise((resolve, reject) => { - observer = { - onBeginUpdateBatch: function() {}, - onEndUpdateBatch: function() {}, - onVisit: function(uri) { - reject(new Error("Unexpected call to onVisit " + uri.spec)); - }, - onTitleChanged: function(uri) { - reject(new Error("Unexpected call to onTitleChanged " + uri.spec)); - }, - onClearHistory: function() { - reject("Unexpected call to onClearHistory"); - }, - onPageChanged: function(uri) { - reject(new Error("Unexpected call to onPageChanged " + uri.spec)); - }, - onFrecencyChanged: function(aURI) { - try { - Assert.ok(!shouldRemove, "Observing onFrecencyChanged"); - Assert.equal(aURI.spec, uri.spec, "Observing effect on the right uri"); - } finally { - resolve(); - } - }, - onManyFrecenciesChanged: function() { - try { - Assert.ok(!shouldRemove, "Observing onManyFrecenciesChanged"); - } finally { - resolve(); - } - }, - onDeleteURI: function(aURI) { - try { - Assert.ok(shouldRemove, "Observing onDeleteURI"); - Assert.equal(aURI.spec, uri.spec, "Observing effect on the right uri"); - } finally { - resolve(); - } - }, - onDeleteVisits: function(aURI) { - Assert.equal(aURI.spec, uri.spec, "Observing onDeleteVisits on the right uri"); - } - }; - }); - PlacesUtils.history.addObserver(observer, false); - - do_print("Performing removal"); - let removed = false; - if (options.useCallback) { - let onRowCalled = false; - removed = yield PlacesUtils.history.remove(removeArg, page => { - Assert.equal(onRowCalled, false, "Callback has not been called yet"); - onRowCalled = true; - Assert.equal(page.url.href, uri.spec, "Callback provides the correct url"); - Assert.equal(page.guid, do_get_guid_for_uri(uri), "Callback provides the correct guid"); - Assert.equal(page.title, title, "Callback provides the correct title"); - Assert.equal(page.frecency, frecencyForUrl(uri), "Callback provides the correct frecency"); - }); - Assert.ok(onRowCalled, "Callback has been called"); - } else { - removed = yield PlacesUtils.history.remove(removeArg); - } - - yield promiseObserved; - PlacesUtils.history.removeObserver(observer); - - Assert.equal(visits_in_database(uri), 0, "History entry has disappeared"); - Assert.notEqual(visits_in_database(WITNESS_URI), 0, "Witness URI still has visits"); - Assert.notEqual(page_in_database(WITNESS_URI), 0, "Witness URI is still here"); - if (shouldRemove) { - Assert.ok(removed, "Something was removed"); - Assert.equal(page_in_database(uri), 0, "Page has disappeared"); - } else { - Assert.ok(!removed, "The page was not removed, as there was a bookmark"); - Assert.notEqual(page_in_database(uri), 0, "The page is still present"); - } - }); - - try { - for (let useCallback of [false, true]) { - for (let addBookmark of [false, true]) { - let options = { useCallback: useCallback, addBookmark: addBookmark }; - yield remover("Testing History.remove() with a single URI", x => x, options); - yield remover("Testing History.remove() with a single string url", x => x.spec, options); - yield remover("Testing History.remove() with a single string guid", x => do_get_guid_for_uri(x), options); - yield remover("Testing History.remove() with a single URI in an array", x => [x], options); - yield remover("Testing History.remove() with a single string url in an array", x => [x.spec], options); - yield remover("Testing History.remove() with a single string guid in an array", x => [do_get_guid_for_uri(x)], options); - } - } - } finally { - yield promiseClearHistory(); - } - return; -}); - -// Test removing a list of pages -add_task(function* test_remove_many() { - const SIZE = 10; - - do_print("Adding a witness page"); - let WITNESS_URI = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove/" + Math.random());; - yield promiseAddVisits(WITNESS_URI); - Assert.ok(page_in_database(WITNESS_URI), "Witness page added"); - - do_print("Generating samples"); - let pages = []; - for (let i = 0; i < SIZE; ++i) { - let uri = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove?sample=" + i + "&salt=" + Math.random()); - let title = "Visit " + i + ", " + Math.random(); - let hasBookmark = i % 3 == 0; - let resolve; - let page = { - uri: uri, - title: title, - hasBookmark: hasBookmark, - // `true` once `onResult` has been called for this page - onResultCalled: false, - // `true` once `onDeleteVisits` has been called for this page - onDeleteVisitsCalled: false, - // `true` once `onFrecencyChangedCalled` has been called for this page - onFrecencyChangedCalled: false, - // `true` once `onDeleteURI` has been called for this page - onDeleteURICalled: false, - }; - do_print("Pushing: " + uri.spec); - pages.push(page); - - yield promiseAddVisits(page); - page.guid = do_get_guid_for_uri(uri); - if (hasBookmark) { - PlacesUtils.bookmarks.insertBookmark( - PlacesUtils.unfiledBookmarksFolderId, - uri, - PlacesUtils.bookmarks.DEFAULT_INDEX, - "test bookmark " + i); - } - Assert.ok(page_in_database(uri), "Page added"); - } - - do_print("Mixing key types and introducing dangling keys"); - let keys = []; - for (let i = 0; i < SIZE; ++i) { - if (i % 4 == 0) { - keys.push(pages[i].uri); - keys.push(NetUtil.newURI("http://example.org/dangling/nsIURI/" + i)); - } else if (i % 4 == 1) { - keys.push(new URL(pages[i].uri.spec)); - keys.push(new URL("http://example.org/dangling/URL/" + i)); - } else if (i % 4 == 2) { - keys.push(pages[i].uri.spec); - keys.push("http://example.org/dangling/stringuri/" + i); - } else { - keys.push(pages[i].guid); - keys.push(("guid_" + i + "_01234567890").substr(0, 12)); - } - } - - let observer = { - onBeginUpdateBatch: function() {}, - onEndUpdateBatch: function() {}, - onVisit: function(aURI) { - Assert.ok(false, "Unexpected call to onVisit " + aURI.spec); - }, - onTitleChanged: function(aURI) { - Assert.ok(false, "Unexpected call to onTitleChanged " + aURI.spec); - }, - onClearHistory: function() { - Assert.ok(false, "Unexpected call to onClearHistory"); - }, - onPageChanged: function(aURI) { - Assert.ok(false, "Unexpected call to onPageChanged " + aURI.spec); - }, - onFrecencyChanged: function(aURI) { - let origin = pages.find(x => x.uri.spec == aURI.spec); - Assert.ok(origin); - Assert.ok(origin.hasBookmark, "Observing onFrecencyChanged on a page with a bookmark"); - origin.onFrecencyChangedCalled = true; - // We do not make sure that `origin.onFrecencyChangedCalled` is `false`, as - }, - onManyFrecenciesChanged: function() { - Assert.ok(false, "Observing onManyFrecenciesChanges, this is most likely correct but not covered by this test"); - }, - onDeleteURI: function(aURI) { - let origin = pages.find(x => x.uri.spec == aURI.spec); - Assert.ok(origin); - Assert.ok(!origin.hasBookmark, "Observing onDeleteURI on a page without a bookmark"); - Assert.ok(!origin.onDeleteURICalled, "Observing onDeleteURI for the first time"); - origin.onDeleteURICalled = true; - }, - onDeleteVisits: function(aURI) { - let origin = pages.find(x => x.uri.spec == aURI.spec); - Assert.ok(origin); - Assert.ok(!origin.onDeleteVisitsCalled, "Observing onDeleteVisits for the first time"); - origin.onDeleteVisitsCalled = true; - } - }; - PlacesUtils.history.addObserver(observer, false); - - do_print("Removing the pages and checking the callbacks"); - let removed = yield PlacesUtils.history.remove(keys, page => { - let origin = pages.find(candidate => candidate.uri.spec == page.url.href); - - Assert.ok(origin, "onResult has a valid page"); - Assert.ok(!origin.onResultCalled, "onResult has not seen this page yet"); - origin.onResultCalled = true; - Assert.equal(page.guid, origin.guid, "onResult has the right guid"); - Assert.equal(page.title, origin.title, "onResult has the right title"); - }); - Assert.ok(removed, "Something was removed"); - - PlacesUtils.history.removeObserver(observer); - - do_print("Checking out results"); - // By now the observers should have been called. - for (let i = 0; i < pages.length; ++i) { - let page = pages[i]; - do_print("Page: " + i); - Assert.ok(page.onResultCalled, "We have reached the page from the callback"); - Assert.ok(visits_in_database(page.uri) == 0, "History entry has disappeared"); - Assert.equal(page_in_database(page.uri) != 0, page.hasBookmark, "Page is present only if it also has bookmarks"); - Assert.equal(page.onFrecencyChangedCalled, page.onDeleteVisitsCalled, "onDeleteVisits was called iff onFrecencyChanged was called"); - Assert.ok(page.onFrecencyChangedCalled ^ page.onDeleteURICalled, "Either onFrecencyChanged or onDeleteURI was called"); - } - - Assert.notEqual(visits_in_database(WITNESS_URI), 0, "Witness URI still has visits"); - Assert.notEqual(page_in_database(WITNESS_URI), 0, "Witness URI is still here"); - - do_print("Cleaning up"); - yield promiseClearHistory(); - -}); - -// Test the various error cases -add_task(function* test_error_cases() { - Assert.throws( - () => PlacesUtils.history.remove(), - /TypeError: Invalid url/, - "History.remove with no argument should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove(null), - /TypeError: Invalid url/, - "History.remove with `null` should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove(undefined), - /TypeError: Invalid url/, - "History.remove with `undefined` should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove("not a guid, obviously"), - /TypeError: .* is not a valid URL/, - "History.remove with an ill-formed guid/url argument should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove({"not the kind of object we know how to handle": true}), - /TypeError: Invalid url/, - "History.remove with an unexpected object should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove([]), - /TypeError: Expected at least one page/, - "History.remove with an empty array should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove([null]), - /TypeError: Invalid url or guid/, - "History.remove with an array containing null should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove(["http://example.org", "not a guid, obviously"]), - /TypeError: .* is not a valid URL/, - "History.remove with an array containing an ill-formed guid/url argument should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove(["0123456789ab"/*valid guid*/, null]), - /TypeError: Invalid url or guid: null/, - "History.remove with an array containing a guid and a second argument that is null should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove(["http://example.org", {"not the kind of object we know how to handle": true}]), - /TypeError: Invalid url/, - "History.remove with an array containing an unexpected objecgt should throw a TypeError" - ); - Assert.throws( - () => PlacesUtils.history.remove("http://example.org", "not a function, obviously"), - /TypeError: Invalid function/, - "History.remove with a second argument that is not a function argument should throw a TypeError" - ); - try { - PlacesUtils.history.remove("http://example.org/I/have/clearly/not/been/added", null); - Assert.ok(true, "History.remove should ignore `null` as a second argument"); - } catch (ex) { - Assert.ok(false, "History.remove should ignore `null` as a second argument"); - } -}); - -function run_test() { - run_next_test(); -} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/history/xpcshell.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/history/xpcshell.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/history/xpcshell.ini 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/history/xpcshell.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -[DEFAULT] -head = head_history.js -tail = - -[test_remove.js] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/nsDummyObserver.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/nsDummyObserver.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/nsDummyObserver.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/nsDummyObserver.js 2014-11-26 21:46:01.000000000 +0000 @@ -3,15 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); const Cc = Components.classes; const Ci = Components.interfaces; // Dummy boomark/history observer function DummyObserver() { - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.notifyObservers(null, "dummy-observer-created", null); + Services.obs.notifyObservers(null, "dummy-observer-created", null); } DummyObserver.prototype = { @@ -19,9 +18,7 @@ onBeginUpdateBatch: function () {}, onEndUpdateBatch: function () {}, onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) { - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.notifyObservers(null, "dummy-observer-visited", null); + Services.obs.notifyObservers(null, "dummy-observer-visited", null); }, onTitleChanged: function () {}, onDeleteURI: function () {}, @@ -33,9 +30,7 @@ //onBeginUpdateBatch: function() {}, //onEndUpdateBatch: function() {}, onItemAdded: function(aItemId, aParentId, aIndex, aItemType, aURI) { - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.notifyObservers(null, "dummy-observer-item-added", null); + Services.obs.notifyObservers(null, "dummy-observer-item-added", null); }, onItemChanged: function () {}, onItemRemoved: function() {}, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_1085291.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_1085291.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_1085291.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_1085291.js 2014-11-26 21:46:01.000000000 +0000 @@ -0,0 +1,42 @@ +add_task(function* () { + // test that nodes inserted by incremental update for bookmarks of all types + // have the extra bookmark properties (bookmarkGuid, dateAdded, lastModified). + + // getFolderContents opens the root node. + let root = PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root; + + function* insertAndTest(bmInfo) { + bmInfo = yield PlacesUtils.bookmarks.insert(bmInfo); + let node = root.getChild(root.childCount - 1); + Assert.equal(node.bookmarkGuid, bmInfo.guid); + Assert.equal(node.dateAdded, bmInfo.dateAdded * 1000); + Assert.equal(node.lastModified, bmInfo.lastModified * 1000); + } + + // Normal bookmark. + yield insertAndTest({ parentGuid: root.bookmarkGuid + , type: PlacesUtils.bookmarks.TYPE_BOOKMARK + , title: "Test Bookmark" + , url: "http://test.url.tld" }); + + // place: query + yield insertAndTest({ parentGuid: root.bookmarkGuid + , type: PlacesUtils.bookmarks.TYPE_BOOKMARK + , title: "Test Query" + , url: "place:folder=BOOKMARKS_MENU" }); + + // folder + yield insertAndTest({ parentGuid: root.bookmarkGuid + , type: PlacesUtils.bookmarks.TYPE_FOLDER + , title: "Test Folder" }); + + // separator + yield insertAndTest({ parentGuid: root.bookmarkGuid + , type: PlacesUtils.bookmarks.TYPE_SEPARATOR }); + + root.containerOpen = false; +}); + +function run_test() { + run_next_test(); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_async_transactions.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_async_transactions.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_async_transactions.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_async_transactions.js 2014-11-26 21:46:01.000000000 +0000 @@ -4,10 +4,11 @@ * 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/. */ -const bmsvc = PlacesUtils.bookmarks; -const tagssvc = PlacesUtils.tagging; -const annosvc = PlacesUtils.annotations; -const PT = PlacesTransactions; +const bmsvc = PlacesUtils.bookmarks; +const tagssvc = PlacesUtils.tagging; +const annosvc = PlacesUtils.annotations; +const PT = PlacesTransactions; +const rootGuid = PlacesUtils.bookmarks.rootGuid; Components.utils.importGlobalProperties(["URL"]); @@ -106,9 +107,6 @@ // index at which items should begin let bmStartIndex = 0; -// get bookmarks root id -let root = PlacesUtils.bookmarksMenuFolderId; - function run_test() { bmsvc.addObserver(observer, false); do_register_cleanup(function () { @@ -248,9 +246,8 @@ do_check_true(aTags.every( t => tagsSet.indexOf(t) != -1 )); } -function* createTestFolderInfo(aTitle = "Test Folder") { - return { parentGuid: yield PlacesUtils.promiseItemGuid(root) - , title: "Test Folder" }; +function createTestFolderInfo(aTitle = "Test Folder") { + return { parentGuid: rootGuid, title: "Test Folder" }; } function isLivemarkTree(aTree) { @@ -315,10 +312,12 @@ yield ensureLivemarkCreatedByAddLivemark(aNew.guid); } -function* ensureBookmarksTreeRestoredCorrectly(aOriginalBookmarksTree) { - let restoredTree = - yield PlacesUtils.promiseBookmarksTree(aOriginalBookmarksTree.guid); - yield ensureEqualBookmarksTrees(aOriginalBookmarksTree, restoredTree); +function* ensureBookmarksTreeRestoredCorrectly(...aOriginalBookmarksTrees) { + for (let originalTree of aOriginalBookmarksTrees) { + let restoredTree = + yield PlacesUtils.promiseBookmarksTree(originalTree.guid); + yield ensureEqualBookmarksTrees(originalTree, restoredTree); + } } function* ensureNonExistent(...aGuids) { @@ -338,7 +337,7 @@ ensureUndoState(txns, undoPosition); } - let txn_a = PT.NewFolder(yield createTestFolderInfo()); + let txn_a = PT.NewFolder(createTestFolderInfo()); yield txn_a.transact(); ensureUndoState([[txn_a]], 0); yield ensureTransactThrowsFor(txn_a); @@ -351,7 +350,7 @@ ensureUndoState(); ensureTransactThrowsFor(txn_a); - let txn_b = PT.NewFolder(yield createTestFolderInfo()); + let txn_b = PT.NewFolder(createTestFolderInfo()); yield PT.batch(function* () { try { yield txn_a.transact(); @@ -375,7 +374,7 @@ add_task(function* test_new_folder_with_annotation() { const ANNO = { name: "TestAnno", value: "TestValue" }; - let folder_info = yield createTestFolderInfo(); + let folder_info = createTestFolderInfo(); folder_info.index = bmStartIndex; folder_info.annotations = [ANNO]; ensureUndoState(); @@ -410,7 +409,7 @@ }); add_task(function* test_new_bookmark() { - let bm_info = { parentGuid: yield PlacesUtils.promiseItemGuid(root) + let bm_info = { parentGuid: rootGuid , url: NetUtil.newURI("http://test_create_item.com") , index: bmStartIndex , title: "Test creating an item" }; @@ -447,7 +446,7 @@ }); add_task(function* test_merge_create_folder_and_item() { - let folder_info = yield createTestFolderInfo(); + let folder_info = createTestFolderInfo(); let bm_info = { url: NetUtil.newURI("http://test_create_item_to_folder.com") , title: "Test Bookmark" , index: bmStartIndex }; @@ -485,7 +484,7 @@ }); add_task(function* test_move_items_to_folder() { - let folder_a_info = yield createTestFolderInfo("Folder A"); + let folder_a_info = createTestFolderInfo("Folder A"); let bkm_a_info = { url: new URL("http://test_move_items.com") , title: "Bookmark A" }; let bkm_b_info = { url: NetUtil.newURI("http://test_move_items.com") @@ -541,7 +540,7 @@ ensureUndoState([[bkm_b_txn, bkm_a_txn, folder_a_txn]], 0); // Test moving items between folders. - let folder_b_info = yield createTestFolderInfo("Folder B"); + let folder_b_info = createTestFolderInfo("Folder B"); let folder_b_txn = PT.NewFolder(folder_b_info); folder_b_info.guid = yield folder_b_txn.transact(); ensureUndoState([ [folder_b_txn] @@ -595,7 +594,7 @@ }); add_task(function* test_remove_folder() { - let folder_level_1_info = yield createTestFolderInfo("Folder Level 1"); + let folder_level_1_info = createTestFolderInfo("Folder Level 1"); let folder_level_2_info = { title: "Folder Level 2" }; let [folder_level_1_txn, folder_level_2_txn] = yield PT.batch(function* () { @@ -688,7 +687,7 @@ , POST_DATA = "post_data" , ANNO = { name: "TestAnno", value: "TestAnnoValue" }; - let folder_info = yield createTestFolderInfo(); + let folder_info = createTestFolderInfo(); folder_info.guid = yield PT.NewFolder(folder_info).transact(); let ensureTags = ensureTagsForURI.bind(null, testURI); @@ -803,7 +802,7 @@ }); add_task(function* test_creating_and_removing_a_separator() { - let folder_info = yield createTestFolderInfo(); + let folder_info = createTestFolderInfo(); let separator_info = {}; let undoEntries = []; @@ -872,7 +871,7 @@ add_task(function* test_add_and_remove_livemark() { let createLivemarkTxn = PT.NewLivemark( { feedUrl: NetUtil.newURI("http://test.remove.livemark") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) + , parentGuid: rootGuid , title: "Test Remove Livemark" }); let guid = yield createLivemarkTxn.transact(); let originalInfo = yield PlacesUtils.promiseBookmarksTree(guid); @@ -913,7 +912,7 @@ }); add_task(function* test_edit_title() { - let bm_info = { parentGuid: yield PlacesUtils.promiseItemGuid(root) + let bm_info = { parentGuid: rootGuid , url: NetUtil.newURI("http://test_create_item.com") , title: "Original Title" }; @@ -951,10 +950,7 @@ add_task(function* test_edit_url() { let oldURI = NetUtil.newURI("http://old.test_editing_item_uri.com/"); let newURI = NetUtil.newURI("http://new.test_editing_item_uri.com/"); - let bm_info = { parentGuid: yield PlacesUtils.promiseItemGuid(root) - , url: oldURI - , tags: ["TestTag"]}; - + let bm_info = { parentGuid: rootGuid, url: oldURI, tags: ["TestTag"] }; function ensureURIAndTags(aPreChangeURI, aPostChangeURI, aOLdURITagsPreserved) { ensureItemsChanged({ guid: bm_info.guid , property: "uri" @@ -1016,8 +1012,8 @@ }); add_task(function* test_edit_keyword() { - let bm_info = { parentGuid: yield PlacesUtils.promiseItemGuid(root) - , url: NetUtil.newURI("http://test.edit.keyword") }; + let bm_info = { parentGuid: rootGuid + , url: NetUtil.newURI("http://test.edit.keyword") }; const KEYWORD = "test_keyword"; bm_info.guid = yield PT.NewBookmark(bm_info).transact(); function ensureKeywordChange(aCurrentKeyword = "") { @@ -1054,9 +1050,9 @@ add_task(function* test_tag_uri() { // This also tests passing uri specs. let bm_info_a = { url: "http://bookmarked.uri" - , parentGuid: yield PlacesUtils.promiseItemGuid(root) }; + , parentGuid: rootGuid }; let bm_info_b = { url: NetUtil.newURI("http://bookmarked2.uri") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) }; + , parentGuid: rootGuid }; let unbookmarked_uri = NetUtil.newURI("http://un.bookmarked.uri"); function* promiseIsBookmarked(aURI) { @@ -1128,10 +1124,10 @@ add_task(function* test_untag_uri() { let bm_info_a = { url: NetUtil.newURI("http://bookmarked.uri") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) + , parentGuid: rootGuid , tags: ["A", "B"] }; let bm_info_b = { url: NetUtil.newURI("http://bookmarked2.uri") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) + , parentGuid: rootGuid , tag: "B" }; yield PT.batch(function* () { @@ -1206,7 +1202,7 @@ add_task(function* test_annotate() { let bm_info = { url: NetUtil.newURI("http://test.item.annotation") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) }; + , parentGuid: rootGuid }; let anno_info = { name: "TestAnno", value: "TestValue" }; function ensureAnnoState(aSet) { ensureAnnotationsSet(bm_info.guid, @@ -1248,7 +1244,7 @@ }); add_task(function* test_annotate_multiple() { - let guid = yield PT.NewFolder(yield createTestFolderInfo()).transact(); + let guid = yield PT.NewFolder(createTestFolderInfo()).transact(); let itemId = yield PlacesUtils.promiseItemId(guid); function AnnoObj(aName, aValue) { @@ -1302,7 +1298,7 @@ }); add_task(function* test_sort_folder_by_name() { - let folder_info = yield createTestFolderInfo(); + let folder_info = createTestFolderInfo(); let url = NetUtil.newURI("http://sort.by.name/"); let preSep = [{ title: i, url } for (i of ["3","2","1"])]; @@ -1349,7 +1345,7 @@ add_task(function* test_livemark_txns() { let livemark_info = { feedUrl: NetUtil.newURI("http://test.feed.uri") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) + , parentGuid: rootGuid , title: "Test Livemark" }; function ensureLivemarkAdded() { ensureItemsAdded({ guid: livemark_info.guid @@ -1396,11 +1392,9 @@ }); add_task(function* test_copy() { - let rootGuid = yield PlacesUtils.promiseItemGuid(root); - function* duplicate_and_test(aOriginalGuid) { - yield duplicateGuid = - yield PT.Copy({ guid: aOriginalGuid, newParentGuid: rootGuid }).transact(); + let txn = PT.Copy({ guid: aOriginalGuid, newParentGuid: rootGuid }); + yield duplicateGuid = yield txn.transact(); let originalInfo = yield PlacesUtils.promiseBookmarksTree(aOriginalGuid); let duplicateInfo = yield PlacesUtils.promiseBookmarksTree(duplicateGuid); yield ensureEqualBookmarksTrees(originalInfo, duplicateInfo, false); @@ -1436,9 +1430,9 @@ let sepTxn = PT.NewSeparator({ parentGuid: rootGuid, index: 1 }); let livemarkTxn = PT.NewLivemark( { feedUrl: new URL("http://test.feed.uri") - , parentGuid: yield PlacesUtils.promiseItemGuid(root) + , parentGuid: rootGuid , title: "Test Livemark", index: 1 }); - let emptyFolderTxn = PT.NewFolder(yield createTestFolderInfo()); + let emptyFolderTxn = PT.NewFolder(createTestFolderInfo()); for (let txn of [livemarkTxn, sepTxn, emptyFolderTxn]) { let guid = yield txn.transact(); yield duplicate_and_test(guid); @@ -1446,8 +1440,7 @@ // Test duplicating a folder having some contents. let filledFolderGuid = yield PT.batch(function *() { - let folderGuid = - yield PT.NewFolder(yield createTestFolderInfo()).transact(); + let folderGuid = yield PT.NewFolder(createTestFolderInfo()).transact(); let nestedFolderGuid = yield PT.NewFolder({ parentGuid: folderGuid , title: "Nested Folder" }).transact(); @@ -1469,9 +1462,7 @@ }); add_task(function* test_array_input_for_batch() { - let rootGuid = yield PlacesUtils.promiseItemGuid(root); - - let folderTxn = PT.NewFolder(yield createTestFolderInfo()); + let folderTxn = PT.NewFolder(createTestFolderInfo()); let folderGuid = yield folderTxn.transact(); let sep1_txn = PT.NewSeparator({ parentGuid: folderGuid }); @@ -1503,9 +1494,7 @@ }); add_task(function* test_copy_excluding_annotations() { - let rootGuid = yield PlacesUtils.promiseItemGuid(root); - - let folderInfo = yield createTestFolderInfo(); + let folderInfo = createTestFolderInfo(); let anno = n => { return { name: n, value: 1 } }; folderInfo.annotations = [anno("a"), anno("b"), anno("c")]; let folderGuid = yield PT.NewFolder(folderInfo).transact(); @@ -1539,7 +1528,6 @@ }); add_task(function* test_invalid_uri_spec_throws() { - let rootGuid = yield PlacesUtils.promiseItemGuid(root); Assert.throws(() => PT.NewBookmark({ parentGuid: rootGuid , url: "invalid uri spec" @@ -1551,3 +1539,120 @@ PT.Tag({ tag: "TheTag" , urls: ["about:blank", "invalid uri spec"] })); }); + +add_task(function* test_annotate_multiple_items() { + let parentGuid = rootGuid; + let guids = [ + yield PT.NewBookmark({ url: "about:blank", parentGuid }).transact(), + yield PT.NewFolder({ title: "Test Folder", parentGuid }).transact()]; + + let annotation = { name: "TestAnno", value: "TestValue" }; + yield PT.Annotate({ guids, annotation }).transact(); + + function *ensureAnnoSet() { + for (let guid of guids) { + let itemId = yield PlacesUtils.promiseItemId(guid); + Assert.equal(annosvc.getItemAnnotation(itemId, annotation.name), + annotation.value); + } + } + function *ensureAnnoUnset() { + for (let guid of guids) { + let itemId = yield PlacesUtils.promiseItemId(guid); + Assert.ok(!annosvc.itemHasAnnotation(itemId, annotation.name)); + } + } + + yield ensureAnnoSet(); + yield PT.undo(); + yield ensureAnnoUnset(); + yield PT.redo(); + yield ensureAnnoSet(); + yield PT.undo(); + yield ensureAnnoUnset(); + + // Cleanup + yield PT.undo(); + yield PT.undo(); + yield ensureNonExistent(...guids); + yield PT.clearTransactionsHistory(); + observer.reset(); +}); + +add_task(function* test_remove_multiple() { + let guids = []; + yield PT.batch(function* () { + let folderGuid = yield PT.NewFolder({ title: "Test Folder" + , parentGuid: rootGuid }).transact(); + let nestedFolderGuid = + yield PT.NewFolder({ title: "Nested Test Folder" + , parentGuid: folderGuid }).transact(); + let nestedSepGuid = yield PT.NewSeparator(nestedFolderGuid).transact(); + + guids.push(folderGuid); + + let bmGuid = + yield PT.NewBookmark({ url: new URL("http://test.bookmark.removed") + , parentGuid: rootGuid }).transact(); + guids.push(bmGuid); + }); + + let originalInfos = [for (guid of guids) + yield PlacesUtils.promiseBookmarksTree(guid)]; + + yield PT.Remove(guids).transact(); + yield ensureNonExistent(...guids); + yield PT.undo(); + yield ensureBookmarksTreeRestoredCorrectly(...originalInfos); + yield PT.redo(); + yield ensureNonExistent(...guids); + yield PT.undo(); + yield ensureBookmarksTreeRestoredCorrectly(...originalInfos); + + // Undo the New* transactions batch. + yield PT.undo(); + yield ensureNonExistent(...guids); + + // Redo it. + yield PT.redo(); + yield ensureBookmarksTreeRestoredCorrectly(...originalInfos); + + // Redo remove. + yield PT.redo(); + yield ensureNonExistent(...guids); + + // Cleanup + yield PT.clearTransactionsHistory(); + observer.reset(); +}); + +add_task(function* test_remove_bookmarks_for_urls() { + let urls = [new URL("http://test.url.1"), new URL("http://test.url.2")]; + let guids = []; + yield PT.batch(function* () { + for (let url of urls) { + for (let title of ["test title a", "test title b"]) { + let txn = PT.NewBookmark({ url, title, parentGuid: rootGuid }); + guids.push(yield txn.transact()); + } + } + }); + + let originalInfos = [for (guid of guids) + yield PlacesUtils.promiseBookmarksTree(guid)]; + + yield PT.RemoveBookmarksForUrls(urls).transact(); + yield ensureNonExistent(...guids); + yield PT.undo(); + yield ensureBookmarksTreeRestoredCorrectly(...originalInfos); + yield PT.redo(); + yield ensureNonExistent(...guids); + yield PT.undo(); + yield ensureBookmarksTreeRestoredCorrectly(...originalInfos); + + // Cleanup. + yield PT.redo(); + yield ensureNonExistent(...guids); + yield PT.clearTransactionsHistory(); + observer.reset(); +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_browserhistory.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_browserhistory.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_browserhistory.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_browserhistory.js 2014-11-26 21:46:01.000000000 +0000 @@ -7,67 +7,59 @@ const TEST_URI = NetUtil.newURI("http://mozilla.com/"); const TEST_SUBDOMAIN_URI = NetUtil.newURI("http://foobar.mozilla.com/"); -add_test(function test_addPage() -{ - promiseAddVisits(TEST_URI).then(function () { - do_check_eq(1, PlacesUtils.history.hasHistoryEntries); - run_next_test(); - }); +add_task(function* test_addPage() { + yield promiseAddVisits(TEST_URI); + do_check_eq(1, PlacesUtils.history.hasHistoryEntries); }); -add_test(function test_removePage() -{ +add_task(function* test_removePage() { PlacesUtils.bhistory.removePage(TEST_URI); do_check_eq(0, PlacesUtils.history.hasHistoryEntries); - run_next_test(); }); -add_test(function test_removePages() -{ +add_task(function* test_removePages() { let pages = []; for (let i = 0; i < 8; i++) { pages.push(NetUtil.newURI(TEST_URI.spec + i)); } - promiseAddVisits(pages.map(function (uri) ({ uri: uri }))).then(function () { - // Bookmarked item should not be removed from moz_places. - const ANNO_INDEX = 1; - const ANNO_NAME = "testAnno"; - const ANNO_VALUE = "foo"; - const BOOKMARK_INDEX = 2; - PlacesUtils.annotations.setPageAnnotation(pages[ANNO_INDEX], - ANNO_NAME, ANNO_VALUE, 0, - Ci.nsIAnnotationService.EXPIRE_NEVER); - PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, - pages[BOOKMARK_INDEX], - PlacesUtils.bookmarks.DEFAULT_INDEX, - "test bookmark"); - PlacesUtils.annotations.setPageAnnotation(pages[BOOKMARK_INDEX], - ANNO_NAME, ANNO_VALUE, 0, - Ci.nsIAnnotationService.EXPIRE_NEVER); - - PlacesUtils.bhistory.removePages(pages, pages.length); - do_check_eq(0, PlacesUtils.history.hasHistoryEntries); - - // Check that the bookmark and its annotation still exist. - do_check_true(PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0) > 0); - do_check_eq(PlacesUtils.annotations.getPageAnnotation(pages[BOOKMARK_INDEX], ANNO_NAME), - ANNO_VALUE); - - // Check the annotation on the non-bookmarked page does not exist anymore. - try { - PlacesUtils.annotations.getPageAnnotation(pages[ANNO_INDEX], ANNO_NAME); - do_throw("did not expire expire_never anno on a not bookmarked item"); - } catch(ex) {} - - // Cleanup. - PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); - promiseClearHistory().then(run_next_test); - }); + yield promiseAddVisits(pages.map(function (uri) ({ uri: uri }))); + // Bookmarked item should not be removed from moz_places. + const ANNO_INDEX = 1; + const ANNO_NAME = "testAnno"; + const ANNO_VALUE = "foo"; + const BOOKMARK_INDEX = 2; + PlacesUtils.annotations.setPageAnnotation(pages[ANNO_INDEX], + ANNO_NAME, ANNO_VALUE, 0, + Ci.nsIAnnotationService.EXPIRE_NEVER); + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + pages[BOOKMARK_INDEX], + PlacesUtils.bookmarks.DEFAULT_INDEX, + "test bookmark"); + PlacesUtils.annotations.setPageAnnotation(pages[BOOKMARK_INDEX], + ANNO_NAME, ANNO_VALUE, 0, + Ci.nsIAnnotationService.EXPIRE_NEVER); + + PlacesUtils.bhistory.removePages(pages, pages.length); + do_check_eq(0, PlacesUtils.history.hasHistoryEntries); + + // Check that the bookmark and its annotation still exist. + do_check_true(PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0) > 0); + do_check_eq(PlacesUtils.annotations.getPageAnnotation(pages[BOOKMARK_INDEX], ANNO_NAME), + ANNO_VALUE); + + // Check the annotation on the non-bookmarked page does not exist anymore. + try { + PlacesUtils.annotations.getPageAnnotation(pages[ANNO_INDEX], ANNO_NAME); + do_throw("did not expire expire_never anno on a not bookmarked item"); + } catch(ex) {} + + // Cleanup. + PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); + yield promiseClearHistory(); }); -add_test(function test_removePagesByTimeframe() -{ +add_task(function* test_removePagesByTimeframe() { let visits = []; let startDate = Date.now() * 1000; for (let i = 0; i < 10; i++) { @@ -77,49 +69,61 @@ }); } - promiseAddVisits(visits).then(function () { - // Delete all pages except the first and the last. - PlacesUtils.bhistory.removePagesByTimeframe(startDate + 1, startDate + 8); - - // Check that we have removed the correct pages. - for (let i = 0; i < 10; i++) { - do_check_eq(page_in_database(NetUtil.newURI(TEST_URI.spec + i)) == 0, - i > 0 && i < 9); - } - - // Clear remaining items and check that all pages have been removed. - PlacesUtils.bhistory.removePagesByTimeframe(startDate, startDate + 9); - do_check_eq(0, PlacesUtils.history.hasHistoryEntries); - run_next_test(); - }); + yield promiseAddVisits(visits); + + // Delete all pages except the first and the last. + PlacesUtils.bhistory.removePagesByTimeframe(startDate + 1, startDate + 8); + + // Check that we have removed the correct pages. + for (let i = 0; i < 10; i++) { + do_check_eq(page_in_database(NetUtil.newURI(TEST_URI.spec + i)) == 0, + i > 0 && i < 9); + } + + // Clear remaining items and check that all pages have been removed. + PlacesUtils.bhistory.removePagesByTimeframe(startDate, startDate + 9); + do_check_eq(0, PlacesUtils.history.hasHistoryEntries); }); -add_test(function test_removePagesFromHost() -{ - promiseAddVisits(TEST_URI).then(function () { - PlacesUtils.bhistory.removePagesFromHost("mozilla.com", true); - do_check_eq(0, PlacesUtils.history.hasHistoryEntries); - run_next_test(); - }); +add_task(function* test_removePagesFromHost() { + yield promiseAddVisits(TEST_URI); + PlacesUtils.bhistory.removePagesFromHost("mozilla.com", true); + do_check_eq(0, PlacesUtils.history.hasHistoryEntries); }); -add_test(function test_removePagesFromHost_keepSubdomains() -{ - promiseAddVisits([{ uri: TEST_URI }, { uri: TEST_SUBDOMAIN_URI }]).then(function () { - PlacesUtils.bhistory.removePagesFromHost("mozilla.com", false); - do_check_eq(1, PlacesUtils.history.hasHistoryEntries); - run_next_test(); - }); +add_task(function* test_removePagesFromHost_keepSubdomains() { + yield promiseAddVisits([{ uri: TEST_URI }, { uri: TEST_SUBDOMAIN_URI }]); + PlacesUtils.bhistory.removePagesFromHost("mozilla.com", false); + do_check_eq(1, PlacesUtils.history.hasHistoryEntries); }); -add_test(function test_removeAllPages() -{ +add_task(function* test_removeAllPages() { PlacesUtils.bhistory.removeAllPages(); do_check_eq(0, PlacesUtils.history.hasHistoryEntries); - run_next_test(); }); -function run_test() -{ +add_task(function* test_getObservers() { + // Ensure that getObservers() invalidates the hasHistoryEntries cache. + yield promiseAddVisits(TEST_URI); + do_check_eq(1, PlacesUtils.history.hasHistoryEntries); + // This is just for testing purposes, never do it. + return new Promise((resolve, reject) => { + DBConn().executeSimpleSQLAsync("DELETE FROM moz_historyvisits", { + handleError: function(error) { + reject(error); + }, + handleResult: function(result) { + }, + handleCompletion: function(result) { + // Just invoking getObservers should be enough to invalidate the cache. + PlacesUtils.history.getObservers(); + do_check_eq(0, PlacesUtils.history.hasHistoryEntries); + resolve(); + } + }); + }); +}); + +function run_test() { run_next_test(); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_history_catobs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_history_catobs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_history_catobs.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_history_catobs.js 2014-11-26 21:46:01.000000000 +0000 @@ -1,46 +1,55 @@ -/* 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/. */ - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); - -// Get services. -let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - -let gDummyCreated = false; -let gDummyVisited = false; - -let observer = { - observe: function(subject, topic, data) { - if (topic == "dummy-observer-created") - gDummyCreated = true; - else if (topic == "dummy-observer-visited") - gDummyVisited = true; - }, - - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIObserver, - Ci.nsISupportsWeakReference, - ]) -}; - -function verify() { - do_check_true(gDummyCreated); - do_check_true(gDummyVisited); - do_test_finished(); -} +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + -// main function run_test() { + run_next_test(); +} + +add_task(function* () { do_load_manifest("nsDummyObserver.manifest"); - os.addObserver(observer, "dummy-observer-created", true); - os.addObserver(observer, "dummy-observer-visited", true); + let dummyCreated = false; + let dummyReceivedOnVisit = false; - do_test_pending(); + Services.obs.addObserver(function created() { + Services.obs.removeObserver(created, "dummy-observer-created"); + dummyCreated = true; + }, "dummy-observer-created", false); + Services.obs.addObserver(function visited() { + Services.obs.removeObserver(visited, "dummy-observer-visited"); + dummyReceivedOnVisit = true; + }, "dummy-observer-visited", false); + + let initialObservers = PlacesUtils.history.getObservers(); + + // Add a common observer, it should be invoked after the category observer. + let notificationsPromised = new Promise((resolve, reject) => { + PlacesUtils.history.addObserver({ + __proto__: NavHistoryObserver.prototype, + onVisit() { + let observers = PlacesUtils.history.getObservers(); + Assert.equal(observers.length, initialObservers.length + 1); + + // Check the common observer is the last one. + for (let i = 0; i < initialObservers.length; ++i) { + Assert.equal(initialObservers[i], observers[i]); + } + + PlacesUtils.history.removeObserver(this); + observers = PlacesUtils.history.getObservers(); + Assert.equal(observers.length, initialObservers.length); + + // Check the category observer has been invoked before this one. + Assert.ok(dummyCreated); + Assert.ok(dummyReceivedOnVisit); + resolve(); + } + }, false); + }); - // Add a visit - promiseAddVisits(uri("http://typed.mozilla.org")).then( - function () do_timeout(1000, verify)); -} + // Add a visit. + yield promiseAddVisits(uri("http://typed.mozilla.org")); + + yield notificationsPromised; +}); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_mozIAsyncLivemarks.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_mozIAsyncLivemarks.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_mozIAsyncLivemarks.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_mozIAsyncLivemarks.js 2014-11-26 21:46:01.000000000 +0000 @@ -192,6 +192,7 @@ do_check_eq(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId); do_check_eq(livemark.index, PlacesUtils.bookmarks.getItemIndex(livemark.id)); do_check_eq(livemark.lastModified, PlacesUtils.bookmarks.getItemLastModified(livemark.id)); + do_check_eq(livemark.dateAdded, PlacesUtils.bookmarks.getItemDateAdded(livemark.id)); do_check_true(livemark.feedURI.equals(FEED_URI)); do_check_eq(livemark.siteURI, null); }); @@ -211,6 +212,7 @@ do_check_eq(livemark.title, "test"); do_check_eq(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId); do_check_eq(livemark.index, PlacesUtils.bookmarks.getItemIndex(livemark.id)); + do_check_eq(livemark.dateAdded, PlacesUtils.bookmarks.getItemDateAdded(livemark.id)); do_check_eq(livemark.lastModified, PlacesUtils.bookmarks.getItemLastModified(livemark.id)); do_check_true(livemark.feedURI.equals(FEED_URI)); do_check_true(livemark.siteURI.equals(SITE_URI)); @@ -287,6 +289,18 @@ checkLivemark(livemark); }); +add_task(function* test_addLivemark_dateAdded_succeeds() { + let dateAdded = new Date("2013-03-01T01:10:00") * 1000; + let livemark = yield PlacesUtils.livemarks.addLivemark( + { title: "test" + , parentId: PlacesUtils.unfiledBookmarksFolderId + , index: PlacesUtils.bookmarks.DEFAULT_INDEX + , feedURI: FEED_URI + , dateAdded + }); + do_check_eq(livemark.dateAdded, dateAdded); +}); + add_task(function test_addLivemark_lastModified_succeeds() { let now = Date.now() * 1000; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_null_interfaces.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_null_interfaces.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_null_interfaces.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_null_interfaces.js 2014-11-26 21:46:01.000000000 +0000 @@ -13,7 +13,7 @@ let testServices = [ ["browser/nav-history-service;1", "nsINavHistoryService", ["queryStringToQueries", "removePagesByTimeframe", "removePagesFromHost", - "removeVisitsByTimeframe"]], + "removeVisitsByTimeframe", "getObservers"]], ["browser/nav-bookmarks-service;1","nsINavBookmarksService", ["createFolder", "getObservers"]], ["browser/livemark-service;2","mozIAsyncLivemarks", ["reloadLivemarks"]], diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_PlacesUtils_promiseHrefAndPostDataForKeyword.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_PlacesUtils_promiseHrefAndPostDataForKeyword.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/test_PlacesUtils_promiseHrefAndPostDataForKeyword.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/test_PlacesUtils_promiseHrefAndPostDataForKeyword.js 2014-11-26 21:46:01.000000000 +0000 @@ -0,0 +1,117 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +add_task(function* test_no_keyword() { + Assert.deepEqual({ href: null, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should not exist"); +}); + +add_task(function* test_add_remove() { + let item1 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "http://example1.com/", + keyword: "test" }); + Assert.deepEqual({ href: item1.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item1.url.href); + + // Add a second url for the same keyword, since it's newer it should be + // returned. + let item2 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "http://example2.com/", + keyword: "test" }); + Assert.deepEqual({ href: item2.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item2.url.href); + + // Now remove item2, should return item1 again. + yield PlacesUtils.bookmarks.remove(item2); + Assert.deepEqual({ href: item1.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item1.url.href); + + // Now remove item1, should return null again. + yield PlacesUtils.bookmarks.remove(item1); + Assert.deepEqual({ href: null, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should not exist"); +}); + +add_task(function* test_change_url() { + let item = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "http://example.com/", + keyword: "test" }); + Assert.deepEqual({ href: item.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item.url.href); + + // Change the bookmark url. + let updatedItem = yield PlacesUtils.bookmarks.update({ guid: item.guid, + url: "http://example2.com" }); + Assert.deepEqual({ href: updatedItem.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + updatedItem.url.href); + yield PlacesUtils.bookmarks.remove(updatedItem); +}); + +add_task(function* test_change_keyword() { + let item = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "http://example.com/", + keyword: "test" }); + Assert.deepEqual({ href: item.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item.url.href); + + // Change the bookmark keywprd. + let updatedItem = yield PlacesUtils.bookmarks.update({ guid: item.guid, + keyword: "test2" }); + Assert.deepEqual({ href: null, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should not exist"); + Assert.deepEqual({ href: updatedItem.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test2")), + "Keyword 'test' should point to " + updatedItem.url.href); + + // Remove the bookmark keyword. + updatedItem = yield PlacesUtils.bookmarks.update({ guid: item.guid, + keyword: "" }); + Assert.deepEqual({ href: null, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should not exist"); + Assert.deepEqual({ href: null, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test2")), + "Keyword 'test' should not exist"); + yield PlacesUtils.bookmarks.remove(updatedItem); +}); + +add_task(function* test_postData() { + let item1 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "http://example1.com/", + keyword: "test" }); + let itemId1 = yield PlacesUtils.promiseItemId(item1.guid); + PlacesUtils.setPostDataForBookmark(itemId1, "testData"); + Assert.deepEqual({ href: item1.url.href, postData: "testData" }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item1.url.href); + + // Add a second url for the same keyword, but without postData. + let item2 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "http://example2.com/", + keyword: "test" }); + Assert.deepEqual({ href: item2.url.href, postData: null }, + (yield PlacesUtils.promiseHrefAndPostDataForKeyword("test")), + "Keyword 'test' should point to " + item2.url.href); + + yield PlacesUtils.bookmarks.remove(item1); + yield PlacesUtils.bookmarks.remove(item2); +}); + +function run_test() { + run_next_test(); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/xpcshell.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/xpcshell.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/tests/unit/xpcshell.ini 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/tests/unit/xpcshell.ini 2014-11-26 21:46:01.000000000 +0000 @@ -55,6 +55,7 @@ [test_485442_crash_bug_nsNavHistoryQuery_GetUri.js] [test_486978_sort_by_date_queries.js] [test_536081.js] +[test_1085291.js] [test_adaptive.js] # Bug 676989: test hangs consistently on Android skip-if = os == "android" @@ -119,6 +120,7 @@ [test_PlacesSearchAutocompleteProvider.js] [test_PlacesUtils_asyncGetBookmarkIds.js] [test_PlacesUtils_lazyobservers.js] +[test_PlacesUtils_promiseHrefAndPostDataForKeyword.js] [test_placesTxn.js] [test_preventive_maintenance.js] # Bug 676989: test hangs consistently on Android diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/UnifiedComplete.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/UnifiedComplete.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/places/UnifiedComplete.js 2014-11-14 09:37:28.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/places/UnifiedComplete.js 2014-11-26 21:46:01.000000000 +0000 @@ -17,7 +17,7 @@ const PREF_ENABLED = [ "autocomplete.enabled", true ]; const PREF_AUTOFILL = [ "autoFill", true ]; const PREF_AUTOFILL_TYPED = [ "autoFill.typed", true ]; -const PREF_AUTOFILL_SEARCHENGINES = [ "autoFill.searchEngines", true ]; +const PREF_AUTOFILL_SEARCHENGINES = [ "autoFill.searchEngines", false ]; const PREF_RESTYLESEARCHES = [ "restyleSearches", false ]; const PREF_DELAY = [ "delay", 50 ]; const PREF_BEHAVIOR = [ "matchBehavior", MATCH_BOUNDARY_ANYWHERE ]; @@ -568,7 +568,10 @@ // Set the default behavior for this search. this._behavior = this._searchString ? Prefs.defaultBehavior : Prefs.emptySearchDefaultBehavior; - this._enableActions = searchParam.split(" ").indexOf("enable-actions") != -1; + + let params = new Set(searchParam.split(" ")); + this._enableActions = params.has("enable-actions"); + this._disablePrivateActions = params.has("disable-private-actions"); this._searchTokens = this.filterTokens(getUnfilteredSearchTokens(this._searchString)); @@ -630,8 +633,14 @@ * @return true if the behavior is set, false otherwise. */ hasBehavior: function (type) { - return this._behavior & - Ci.mozIPlacesAutoComplete["BEHAVIOR_" + type.toUpperCase()]; + let behavior = Ci.mozIPlacesAutoComplete["BEHAVIOR_" + type.toUpperCase()]; + + if (this._disablePrivateActions && + behavior == Ci.mozIPlacesAutoComplete.BEHAVIOR_OPENPAGE) { + return false; + } + + return this._behavior & behavior; }, /** @@ -768,7 +777,7 @@ let hasFirstResult = false; if (this._searchTokens.length > 0 && - PlacesUtils.bookmarks.getURIForKeyword(this._searchTokens[0])) { + (yield PlacesUtils.promiseHrefAndPostDataForKeyword(this._searchTokens[0])).href) { // This may be a keyword of a bookmark. queries.unshift(this._keywordQuery); hasFirstResult = true; @@ -964,7 +973,6 @@ comment: match.engineName, icon: match.iconUrl, style: "action searchengine", - finalCompleteValue: this._trimmedOriginalSearchString, frecency: FRECENCY_SEARCHENGINES_DEFAULT, }); }, @@ -1017,7 +1025,6 @@ value: value, comment: uri.spec, style: "action visiturl", - finalCompleteValue: this._originalSearchString, frecency: 0, }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/printing/content/printUtils.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/printing/content/printUtils.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/printing/content/printUtils.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/printing/content/printUtils.js 2014-11-26 21:46:01.000000000 +0000 @@ -147,7 +147,7 @@ aWindow = window.content; } - if (Cu.isCrossProcessWrapper(aWindow)) { + if (Components.utils.isCrossProcessWrapper(aWindow)) { if (!aBrowser) { throw new Error("PrintUtils.print expects a remote browser passed as " + "an argument if the content window is a CPOW."); @@ -155,9 +155,9 @@ } else { // For content windows coming from non-remote browsers, the browser can // be resolved as the chromeEventHandler. - aBrowser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) + aBrowser = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIWebNavigation) + .QueryInterface(Components.interfaces.nsIDocShell) .chromeEventHandler; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/satchel/nsFormFillController.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/satchel/nsFormFillController.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/satchel/nsFormFillController.cpp 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/satchel/nsFormFillController.cpp 2014-11-26 21:46:01.000000000 +0000 @@ -36,6 +36,7 @@ #include "nsIDOMNSEditableElement.h" #include "nsContentUtils.h" #include "nsILoadContext.h" +#include "nsIFrame.h" using namespace mozilla::dom; @@ -948,6 +949,36 @@ case nsIDOMKeyEvent::DOM_VK_DOWN: case nsIDOMKeyEvent::DOM_VK_LEFT: case nsIDOMKeyEvent::DOM_VK_RIGHT: + { + // Get the writing-mode of the relevant input element, + // so that we can remap arrow keys if necessary. + mozilla::WritingMode wm; + if (mFocusedInputNode && mFocusedInputNode->IsElement()) { + mozilla::dom::Element *elem = mFocusedInputNode->AsElement(); + nsIFrame *frame = elem->GetPrimaryFrame(); + if (frame) { + wm = frame->GetWritingMode(); + } + } + if (wm.IsVertical()) { + switch (k) { + case nsIDOMKeyEvent::DOM_VK_LEFT: + k = wm.IsVerticalLR() ? nsIDOMKeyEvent::DOM_VK_UP + : nsIDOMKeyEvent::DOM_VK_DOWN; + break; + case nsIDOMKeyEvent::DOM_VK_RIGHT: + k = wm.IsVerticalLR() ? nsIDOMKeyEvent::DOM_VK_DOWN + : nsIDOMKeyEvent::DOM_VK_UP; + break; + case nsIDOMKeyEvent::DOM_VK_UP: + k = nsIDOMKeyEvent::DOM_VK_LEFT; + break; + case nsIDOMKeyEvent::DOM_VK_DOWN: + k = nsIDOMKeyEvent::DOM_VK_RIGHT; + break; + } + } + } mController->HandleKeyNavigation(k, &cancel); break; case nsIDOMKeyEvent::DOM_VK_ESCAPE: diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/search/nsSearchService.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/search/nsSearchService.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/search/nsSearchService.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/search/nsSearchService.js 2014-11-26 21:46:01.000000000 +0000 @@ -3793,16 +3793,23 @@ } } - // Array for the remaining engines, alphabetically sorted - var alphaEngines = []; + // Array for the remaining engines, alphabetically sorted. + let alphaEngines = []; for each (engine in this._engines) { if (!(engine.name in addedEngines)) alphaEngines.push(this._engines[engine.name]); } - alphaEngines = alphaEngines.sort(function (a, b) { - return a.name.localeCompare(b.name); - }); + + let locale = Cc["@mozilla.org/intl/nslocaleservice;1"] + .getService(Ci.nsILocaleService) + .newLocale(getLocale()); + let collation = Cc["@mozilla.org/intl/collation-factory;1"] + .createInstance(Ci.nsICollationFactory) + .CreateCollation(locale); + const strength = Ci.nsICollation.kCollationCaseInsensitiveAscii; + let comparator = (a, b) => collation.compareString(strength, a.name, b.name); + alphaEngines.sort(comparator); return this.__sortedEngines = this.__sortedEngines.concat(alphaEngines); }, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/search/nsSearchSuggestions.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/search/nsSearchSuggestions.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/search/nsSearchSuggestions.js 2014-11-14 09:37:29.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/search/nsSearchSuggestions.js 2014-11-26 21:46:01.000000000 +0000 @@ -86,13 +86,17 @@ */ onResultsReady: function(searchString, results, comments, formHistoryResult) { if (this._listener) { + // Create a copy of the results array to use as labels, since + // FormAutoCompleteResult doesn't like being passed the same array + // for both. + let labels = results.slice(); let result = new FormAutoCompleteResult( searchString, Ci.nsIAutoCompleteResult.RESULT_SUCCESS, 0, "", results, - results, + labels, comments, formHistoryResult); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/telemetry/Histograms.json thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/telemetry/Histograms.json --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/telemetry/Histograms.json 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/telemetry/Histograms.json 2014-11-26 21:46:01.000000000 +0000 @@ -322,7 +322,7 @@ "expires_in_version": "never", "kind": "enumerated", "n_values": 10, - "description": "Use of SpiderMonkey's deprecated language extensions in web content: ForEach, DestructuringForIn, LegacyGenerator, ExpressionClosure" + "description": "Use of SpiderMonkey's deprecated language extensions in web content: ForEach=0, DestructuringForIn=1, LegacyGenerator=2, ExpressionClosure=3, LetBlock=4, LetExpression=5" }, "TELEMETRY_PING": { "expires_in_version": "default", @@ -3512,6 +3512,13 @@ "n_buckets": 30, "description": "Average paint duration during any tab open/close animation (excluding tabstrip scroll)" }, + "FX_REFRESH_DRIVER_FRAME_DELAY_MS": { + "expires_in_version": "default", + "kind": "exponential", + "high": "10000", + "n_buckets": 50, + "description": "Delay in ms between the target and the actual handling time of the frame at refresh driver" + }, "FX_TAB_SWITCH_UPDATE_MS": { "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", @@ -6555,6 +6562,12 @@ "n_buckets": 10, "description": "How many permanent certificate overrides a user has stored." }, + "SSL_SERVER_AUTH_EKU": { + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 10, + "description": "Presence of of the Server Authenticaton EKU in accepted SSL server certificates (0=No EKU, 1=EKU present and has id_kp_serverAuth, 2=EKU present and has id_kp_serverAuth as well as some other EKU, 3=EKU present but does not contain id_kp_serverAuth)" + }, "TELEMETRY_TEST_EXPIRED": { "expires_in_version": "4.0a1", "kind": "flag", @@ -6594,6 +6607,12 @@ "n_buckets": 10, "extended_statistics_ok": true }, + "CERT_VALIDATION_SUCCESS_BY_CA": { + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 256, + "description": "Successful SSL server cert validations by CA (see RootHashes.inc for names of CAs)" + }, "CERT_PINNING_FAILURES_BY_CA": { "alert_emails": ["pinning@mozilla.org"], "expires_in_version": "never", @@ -6775,6 +6794,34 @@ "n_buckets": 10, "description": "Sidebar showing: seconds that the sidebar has been opened" }, + "SHUTDOWN_PHASE_DURATION_TICKS_QUIT_APPLICATION": { + "expires_in_version": "never", + "kind": "exponential", + "high": 65, + "n_buckets": 10, + "description": "Duration of shutdown phase quit-application, as measured by the shutdown terminator, in seconds of activity" + }, + "SHUTDOWN_PHASE_DURATION_TICKS_PROFILE_CHANGE_TEARDOWN": { + "expires_in_version": "never", + "kind": "exponential", + "high": 65, + "n_buckets": 10, + "description": "Duration of shutdown phase profile-change-teardown, as measured by the shutdown terminator, in seconds of activity" + }, + "SHUTDOWN_PHASE_DURATION_TICKS_XPCOM_WILL_SHUTDOWN": { + "expires_in_version": "never", + "kind": "exponential", + "high": 65, + "n_buckets": 10, + "description": "Duration of shutdown phase xpcom-will-shutdown, as measured by the shutdown terminator, in seconds of activity" + }, + "SHUTDOWN_PHASE_DURATION_TICKS_PROFILE_BEFORE_CHANGE": { + "expires_in_version": "never", + "kind": "exponential", + "high": 65, + "n_buckets": 10, + "description": "Duration of shutdown phase profile-before-change, as measured by the shutdown terminator, in seconds of activity" + }, "BR_9_2_1_SUBJECT_ALT_NAMES": { "expires_in_version": "never", "kind": "enumerated", @@ -6833,5 +6880,16 @@ "expires_in_version": "40", "kind": "boolean", "description": "Whether the e10s pref was set but it was blocked from running due to blacklisted conditions" + }, + "ONBEFOREUNLOAD_PROMPT_ACTION" : { + "expires_in_version": "45", + "kind": "enumerated", + "n_values": 3, + "description": "What button a user clicked in an onbeforeunload prompt. (Stay on Page = 0, Leave Page = 1, prompt aborted = 2)" + }, + "ONBEFOREUNLOAD_PROMPT_COUNT" : { + "expires_in_version": "45", + "kind": "count", + "description": "How many onbeforeunload prompts has the user encountered in their session?" } } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/moz.build 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/moz.build 2014-11-26 21:46:02.000000000 +0000 @@ -4,6 +4,8 @@ # 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/. +XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini'] + SOURCES += [ 'nsTerminator.cpp', ] @@ -13,6 +15,7 @@ ] EXTRA_COMPONENTS += [ + 'nsTerminatorTelemetry.js', 'terminator.manifest', ] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/nsTerminator.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/nsTerminator.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/nsTerminator.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/nsTerminator.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -18,8 +18,14 @@ #include "nsTerminator.h" #include "prthread.h" +#include "prmon.h" +#include "plstr.h" +#include "prio.h" + #include "nsString.h" #include "nsServiceManagerUtils.h" +#include "nsDirectoryServiceUtils.h" +#include "nsAppDirectoryServiceDefs.h" #include "nsIObserverService.h" #include "nsIPrefService.h" @@ -28,11 +34,14 @@ #endif #include "mozilla/ArrayUtils.h" +#include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" +#include "mozilla/MemoryChecking.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/UniquePtr.h" #include "mozilla/unused.h" +#include "mozilla/Telemetry.h" // Normally, the number of milliseconds that AsyncShutdown waits until // it decides to crash is specified as a preference. We use the @@ -51,29 +60,76 @@ namespace { -/** - * Set to `true` by the main thread whenever we pass a shutdown phase, - * which means that the shutdown is still ongoing. Reset to `false` by - * the Terminator thread, once it has acknowledged the progress. - */ -Atomic gProgress(false); +// Utility function: create a thread that is non-joinable, +// does not prevent the process from terminating, is never +// cooperatively scheduled, and uses a default stack size. +PRThread* CreateSystemThread(void (*start)(void* arg), + void* arg) +{ + PRThread* thread = PR_CreateThread( + PR_SYSTEM_THREAD, /* This thread will not prevent the process from terminating */ + start, + arg, + PR_PRIORITY_LOW, + PR_GLOBAL_THREAD /* Make sure that the thread is never cooperatively scheduled */, + PR_UNJOINABLE_THREAD, + 0 /* Use default stack size */ + ); + MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(thread); // This pointer will never be deallocated. + return thread; +} + + +//////////////////////////////////////////// +// +// The watchdog +// +// This nspr thread is in charge of crashing the process if any stage of shutdown +// lasts more than some predefined duration. As a side-effect, it measures the +// duration of each stage of shutdown. +// + +// The heartbeat of the operation. +// +// Main thread: +// +// * Whenever a shutdown step has been completed, the main thread +// swaps gHeartbeat to 0 to mark that the shutdown process is still +// progressing. The value swapped away indicates the number of ticks +// it took for the shutdown step to advance. +// +// Watchdog thread: +// +// * Every tick, the watchdog thread increments gHearbeat atomically. +// +// A note about precision: +// Since gHeartbeat is generally reset to 0 between two ticks, this means +// that gHeartbeat stays at 0 less than one tick. Consequently, values +// extracted from gHeartbeat must be considered rounded up. +Atomic gHeartbeat(0); struct Options { - int32_t crashAfterMS; + /** + * How many ticks before we should crash the process. + */ + uint32_t crashAfterTicks; }; +/** + * Entry point for the watchdog thread + */ void -Run(void* arg) +RunWatchdog(void* arg) { PR_SetCurrentThreadName("Shutdown Hang Terminator"); // Let's copy and deallocate options, that's one less leak to worry // about. UniquePtr options((Options*)arg); - int32_t crashAfterMS = options->crashAfterMS; + uint32_t crashAfterTicks = options->crashAfterTicks; options = nullptr; - int32_t timeToLive = crashAfterMS; + const uint32_t timeToLive = crashAfterTicks; while (true) { // // We do not want to sleep for the entire duration, @@ -86,14 +142,8 @@ // more reasonable. // PR_Sleep(TICK_DURATION); - if (gProgress.exchange(false)) { - // We have passed at least one shutdown phase while waiting. - // Shutdown is still alive, reset the countdown. - timeToLive = crashAfterMS; - continue; - } - timeToLive -= TICK_DURATION; - if (timeToLive >= 0) { + + if (gHeartbeat++ < timeToLive) { continue; } @@ -102,20 +152,177 @@ } } -} // anonymous namespace +//////////////////////////////////////////// +// +// Writer thread +// +// This nspr thread is in charge of writing to disk statistics produced by the +// watchdog thread and collected by the main thread. Note that we use a nspr +// thread rather than usual XPCOM I/O simply because we outlive XPCOM and its +// threads. +// + +// Utility class, used by UniquePtr<> to close nspr files. +class PR_CloseDelete +{ +public: + MOZ_CONSTEXPR PR_CloseDelete() {} + + PR_CloseDelete(const PR_CloseDelete& aOther) + {} -static char const *const sObserverTopics[] = { - "quit-application", - "profile-change-teardown", - "profile-before-change", - "xpcom-will-shutdown", - "xpcom-shutdown", + void operator()(PRFileDesc* aPtr) const + { + PR_Close(aPtr); + } }; +// +// Communication between the main thread and the writer thread. +// +// Main thread: +// +// * Whenever a shutdown step has been completed, the main thread +// obtains the number of ticks from the watchdog threads, builds +// a string representing all the data gathered so far, places +// this string in `gWriteData`, and wakes up the writer thread +// using `gWriteReady`. If `gWriteData` already contained a non-null +// pointer, this means that the writer thread is lagging behind the +// main thread, and the main thread cleans up the memory. +// +// Writer thread: +// +// * When awake, the writer thread swaps `gWriteData` to nullptr. If +// `gWriteData` contained data to write, the . If so, the writer +// thread writes the data to a file named "ShutdownDuration.json.tmp", +// then moves that file to "ShutdownDuration.json" and cleans up the +// data. If `gWriteData` contains a nullptr, the writer goes to sleep +// until it is awkened using `gWriteReady`. +// +// +// The data written by the writer thread will be read by another +// module upon the next restart and fed to Telemetry. +// +Atomic gWriteData(nullptr); +PRMonitor* gWriteReady = nullptr; + +void RunWriter(void* arg) +{ + PR_SetCurrentThreadName("Shutdown Statistics Writer"); + + MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(arg); + // Shutdown will generally complete before we have a chance to + // deallocate. This is not a leak. + + // Setup destinationPath and tmpFilePath + + nsCString destinationPath(static_cast(arg)); + nsAutoCString tmpFilePath; + tmpFilePath.Append(destinationPath); + tmpFilePath.AppendLiteral(".tmp"); + + // Cleanup any file leftover from a previous run + unused << PR_Delete(tmpFilePath.get()); + unused << PR_Delete(destinationPath.get()); + + while (true) { + // + // Check whether we have received data from the main thread. + // + // We perform the check before waiting on `gWriteReady` as we may + // have received data while we were busy writing. + // + // Also note that gWriteData may have been modified several times + // since we last checked. That's ok, we are not losing any important + // data (since we keep adding data), and we are not leaking memory + // (since the main thread deallocates any data that hasn't been + // consumed by the writer thread). + // + UniquePtr data(gWriteData.exchange(nullptr)); + if (!data) { + // Data is not available yet. + // Wait until the main thread provides it. + PR_EnterMonitor(gWriteReady); + PR_Wait(gWriteReady, PR_INTERVAL_NO_TIMEOUT); + PR_ExitMonitor(gWriteReady); + continue; + } + + MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(data.get()); + // Shutdown may complete before we have a chance to deallocate. + // This is not a leak. + + // + // Write to a temporary file + // + // In case of any error, we simply give up. Since the data is + // hardly critical, we don't want to spend too much effort + // salvaging it. + // + UniquePtr + tmpFileDesc(PR_Open(tmpFilePath.get(), + PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE, + 00600)); + + // Shutdown may complete before we have a chance to close the file. + // This is not a leak. + MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(tmpFileDesc.get()); + + if (tmpFileDesc == nullptr) { + break; + } + if (PR_Write(tmpFileDesc.get(), data->get(), data->Length()) == -1) { + break; + } + tmpFileDesc.reset(); + + // + // Rename on top of destination file. + // + // This is not sufficient to guarantee that the destination file + // will be written correctly, but, again, we don't care enough + // about the data to make more efforts. + // + if (PR_Rename(tmpFilePath.get(), destinationPath.get()) != PR_SUCCESS) { + break; + } + } +} + +/** + * A step during shutdown. + * + * Shutdown is divided in steps, which all map to an observer + * notification. The duration of a step is defined as the number of + * ticks between the time we receive a notification and the next one. + */ +struct ShutdownStep +{ + char const* const mTopic; + int mTicks; + + MOZ_CONSTEXPR ShutdownStep(const char *const topic) + : mTopic(topic) + , mTicks(-1) + {} + +}; + +static ShutdownStep sShutdownSteps[] = { + ShutdownStep("quit-application"), + ShutdownStep("profile-change-teardown"), + ShutdownStep("profile-before-change"), + ShutdownStep("xpcom-will-shutdown"), + ShutdownStep("xpcom-shutdown"), +}; + +} // anonymous namespace + NS_IMPL_ISUPPORTS(nsTerminator, nsIObserver) nsTerminator::nsTerminator() : mInitialized(false) + , mCurrentStep(-1) { } @@ -128,45 +335,92 @@ return NS_ERROR_UNEXPECTED; } - for (size_t i = 0; i < ArrayLength(sObserverTopics); ++i) { - DebugOnly rv = os->AddObserver(this, sObserverTopics[i], false); + for (size_t i = 0; i < ArrayLength(sShutdownSteps); ++i) { + DebugOnly rv = os->AddObserver(this, sShutdownSteps[i].mTopic, false); #if defined(DEBUG) NS_WARN_IF(NS_FAILED(rv)); #endif // defined(DEBUG) } + return NS_OK; } -// Actually launch the thread. This takes place at the first sign of shutdown. +// Actually launch these threads. This takes place at the first sign of shutdown. void -nsTerminator::Start() { - // Determine how long we need to wait +nsTerminator::Start() +{ + MOZ_ASSERT(!mInitialized); + StartWatchdog(); + StartWriter(); + mInitialized = true; +} +// Prepare, allocate and start the watchdog thread. +// By design, it will never finish, nor be deallocated. +void +nsTerminator::StartWatchdog() +{ int32_t crashAfterMS = Preferences::GetInt("toolkit.asyncshutdown.crash_timeout", FALLBACK_ASYNCSHUTDOWN_CRASH_AFTER_MS); + // Ignore negative values + if (crashAfterMS <= 0) { + crashAfterMS = FALLBACK_ASYNCSHUTDOWN_CRASH_AFTER_MS; + } // Add a little padding, to ensure that we do not crash before // AsyncShutdown. - crashAfterMS += ADDITIONAL_WAIT_BEFORE_CRASH_MS; + if (crashAfterMS > INT32_MAX - ADDITIONAL_WAIT_BEFORE_CRASH_MS) { + // Defend against overflow + crashAfterMS = INT32_MAX; + } else { + crashAfterMS += ADDITIONAL_WAIT_BEFORE_CRASH_MS; + } UniquePtr options(new Options()); - options->crashAfterMS = crashAfterMS; + options->crashAfterTicks = crashAfterMS / TICK_DURATION; - // Allocate and start the thread. - // By design, it will never finish, nor be deallocated. - DebugOnly thread = PR_CreateThread( - PR_SYSTEM_THREAD, /* This thread will not prevent the process from terminating */ - Run, - options.release(), - PR_PRIORITY_LOW, - PR_GLOBAL_THREAD /* Make sure that the thread is never cooperatively scheduled */, - PR_UNJOINABLE_THREAD, - 0 /* Use default stack size */ - ); + DebugOnly watchdogThread = CreateSystemThread(RunWatchdog, + options.release()); + MOZ_ASSERT(watchdogThread); +} - MOZ_ASSERT(thread); - mInitialized = true; +// Prepare, allocate and start the writer thread. By design, it will never +// finish, nor be deallocated. In case of error, we degrade +// gracefully to not writing Telemetry data. +void +nsTerminator::StartWriter() +{ + + if (!Telemetry::CanRecord()) { + return; + } + nsCOMPtr profLD; + nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, + getter_AddRefs(profLD)); + if (NS_FAILED(rv)) { + return; + } + + rv = profLD->Append(NS_LITERAL_STRING("ShutdownDuration.json")); + if (NS_FAILED(rv)) { + return; + } + + nsAutoString path; + rv = profLD->GetPath(path); + if (NS_FAILED(rv)) { + return; + } + + gWriteReady = PR_NewMonitor(); + MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(gWriteReady); // We will never deallocate this object + PRThread* writerThread = CreateSystemThread(RunWriter, + ToNewUTF8String(path)); + + if (!writerThread) { + return; + } } NS_IMETHODIMP @@ -185,19 +439,101 @@ Start(); } - // Inform the thread that we have advanced by one phase. - gProgress.exchange(true); - -#if defined(MOZ_CRASHREPORTER) - // In case of crash, we wish to know where in shutdown we are - unused << CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ShutdownProgress"), - nsAutoCString(aTopic)); -#endif // defined(MOZ_CRASH_REPORTER) + UpdateHeartbeat(aTopic); + UpdateTelemetry(); + UpdateCrashReport(aTopic); + // Perform a little cleanup nsCOMPtr os = mozilla::services::GetObserverService(); MOZ_RELEASE_ASSERT(os); (void)os->RemoveObserver(this, aTopic); + return NS_OK; } +void +nsTerminator::UpdateHeartbeat(const char* aTopic) +{ + // Reset the clock, find out how long the current phase has lasted. + uint32_t ticks = gHeartbeat.exchange(0); + if (mCurrentStep > 0) { + sShutdownSteps[mCurrentStep].mTicks = ticks; + } + + // Find out where we now are in the current shutdown. + // Don't assume that shutdown takes place in the expected order. + int nextStep = -1; + for (size_t i = 0; i < ArrayLength(sShutdownSteps); ++i) { + if (strcmp(sShutdownSteps[i].mTopic, aTopic) == 0) { + nextStep = i; + break; + } + } + MOZ_ASSERT(nextStep != -1); + mCurrentStep = nextStep; +} + +void +nsTerminator::UpdateTelemetry() +{ + if (!Telemetry::CanRecord() || !gWriteReady) { + return; + } + + // + // We need Telemetry data on the effective duration of each step, + // to be able to tune the time-to-crash of each of both the + // Terminator and AsyncShutdown. However, at this stage, it is too + // late to record such data into Telemetry, so we write it to disk + // and read it upon the next startup. + // + + // Build JSON. + UniquePtr telemetryData(new nsCString()); + telemetryData->AppendLiteral("{"); + size_t fields = 0; + for (size_t i = 0; i < ArrayLength(sShutdownSteps); ++i) { + if (sShutdownSteps[i].mTicks < 0) { + // Ignore this field. + continue; + } + if (fields++ > 0) { + telemetryData->Append(", "); + } + telemetryData->AppendLiteral("\""); + telemetryData->Append(sShutdownSteps[i].mTopic); + telemetryData->AppendLiteral("\": "); + telemetryData->AppendInt(sShutdownSteps[i].mTicks); + } + telemetryData->AppendLiteral("}"); + + if (fields == 0) { + // Nothing to write + return; + } + + // + // Send data to the worker thread. + // + delete gWriteData.exchange(telemetryData.release()); // Clear any data that hasn't been written yet + + // In case the worker thread was sleeping, wake it up. + PR_EnterMonitor(gWriteReady); + PR_Notify(gWriteReady); + PR_ExitMonitor(gWriteReady); +} + +void +nsTerminator::UpdateCrashReport(const char* aTopic) +{ +#if defined(MOZ_CRASHREPORTER) + // In case of crash, we wish to know where in shutdown we are + nsAutoCString report(aTopic); + + unused << CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ShutdownProgress"), + report); +#endif // defined(MOZ_CRASH_REPORTER) +} + + } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/nsTerminator.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/nsTerminator.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/nsTerminator.h 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/nsTerminator.h 2014-11-26 21:46:02.000000000 +0000 @@ -22,10 +22,17 @@ private: nsresult SelfInit(); void Start(); + void StartWatchdog(); + void StartWriter(); + + void UpdateHeartbeat(const char* aTopic); + void UpdateTelemetry(); + void UpdateCrashReport(const char* aTopic); ~nsTerminator() {} bool mInitialized; + int32_t mCurrentStep; }; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/nsTerminatorTelemetry.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/nsTerminatorTelemetry.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/nsTerminatorTelemetry.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/nsTerminatorTelemetry.js 2014-11-26 21:46:02.000000000 +0000 @@ -0,0 +1,105 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */ + +"use strict"; + +/** + * Read the data saved by nsTerminator during shutdown and feed it to the + * relevant telemetry histograms. + */ + +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, "OS", + "resource://gre/modules/osfile.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/Promise.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "setTimeout", + "resource://gre/modules/Timer.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Services", + "resource://gre/modules/Services.jsm"); + +function nsTerminatorTelemetry() {} + +let HISTOGRAMS = { + "quit-application": "SHUTDOWN_PHASE_DURATION_TICKS_QUIT_APPLICATION", + "profile-change-teardown": "SHUTDOWN_PHASE_DURATION_TICKS_PROFILE_CHANGE_TEARDOWN", + "profile-before-change": "SHUTDOWN_PHASE_DURATION_TICKS_PROFILE_BEFORE_CHANGE", + "xpcom-will-shutdown": "SHUTDOWN_PHASE_DURATION_TICKS_XPCOM_WILL_SHUTDOWN", +}; + +nsTerminatorTelemetry.prototype = { + classID: Components.ID("{3f78ada1-cba2-442a-82dd-d5fb300ddea7}"), + + _xpcom_factory: XPCOMUtils.generateSingletonFactory(nsTerminatorTelemetry), + + ////////////////////////////////////////////////////////////////////////////// + //// nsISupports + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), + + ////////////////////////////////////////////////////////////////////////////// + //// nsIObserver + + observe: function DS_observe(aSubject, aTopic, aData) + { + Task.spawn(function*() { + // + // This data is hardly critical, reading it can wait for a few seconds. + // + yield new Promise(resolve => setTimeout(resolve, 3000)); + + let PATH = OS.Path.join(OS.Constants.Path.localProfileDir, + "ShutdownDuration.json"); + let raw; + try { + raw = yield OS.File.read(PATH, { encoding: "utf-8" }); + } catch (ex if ex.becauseNoSuchFile) { + return; + } + // Let other errors be reported by Promise's error-reporting. + + // Clean up + OS.File.remove(PATH); + OS.File.remove(PATH + ".tmp"); + + let data = JSON.parse(raw); + for (let k of Object.keys(data)) { + let id = HISTOGRAMS[k]; + try { + let histogram = Services.telemetry.getHistogramById(id); + if (!histogram) { + throw new Error("Unknown histogram " + id); + } + + histogram.add(Number.parseInt(data[k])); + } catch (ex) { + // Make sure that the error is reported and causes test failures, + // but otherwise, ignore it. + Promise.reject(ex); + continue; + } + } + + // Inform observers that we are done. + Services.obs.notifyObservers(null, + "shutdown-terminator-telemetry-updated", + ""); + }); + }, +}; + +//////////////////////////////////////////////////////////////////////////////// +//// Module + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsTerminatorTelemetry]); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/terminator.manifest thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/terminator.manifest --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/terminator.manifest 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/terminator.manifest 2014-11-26 21:46:02.000000000 +0000 @@ -1,2 +1,5 @@ category profile-after-change nsTerminator @mozilla.org/toolkit/shutdown-terminator;1 +component {3f78ada1-cba2-442a-82dd-d5fb300ddea7} nsTerminatorTelemetry.js +contract @mozilla.org/toolkit/shutdown-terminator-telemetry;1 {3f78ada1-cba2-442a-82dd-d5fb300ddea7} +category profile-after-change nsTerminatorTelemetry @mozilla.org/toolkit/shutdown-terminator-telemetry;1 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_record.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_record.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_record.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_record.js 2014-11-26 21:46:02.000000000 +0000 @@ -0,0 +1,108 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + + +// Test that the Shutdown Terminator records durations correctly + +const Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; + +Cu.import("resource://gre/modules/Services.jsm", this); +Cu.import("resource://gre/modules/osfile.jsm", this); +Cu.import("resource://gre/modules/Timer.jsm", this); +Cu.import("resource://gre/modules/Task.jsm", this); + +let {Path, File, Constants} = OS; + +let PATH; +let PATH_TMP; +let terminator; + +add_task(function* init() { + do_get_profile(); + PATH = Path.join(Constants.Path.localProfileDir, "ShutdownDuration.json"); + PATH_TMP = PATH + ".tmp"; + + // Initialize the terminator + // (normally, this is done through the manifest file, but xpcshell + // doesn't take them into account). + do_print("Initializing the Terminator"); + terminator = Cc["@mozilla.org/toolkit/shutdown-terminator;1"]. + createInstance(Ci.nsIObserver); + terminator.observe(null, "profile-after-change", null); +}); + +let promiseShutdownDurationData = Task.async(function*() { + // Wait until PATH exists. + // Timeout if it is never created. + do_print("Waiting for file creation: " + PATH); + while (true) { + if ((yield OS.File.exists(PATH))) { + break; + } + + do_print("The file does not exist yet. Waiting 1 second."); + yield new Promise(resolve => setTimeout(resolve, 1000)); + } + + do_print("The file has been created"); + let raw = yield OS.File.read(PATH, { encoding: "utf-8"} ); + do_print(raw); + return JSON.parse(raw); +}); + +add_task(function* test_record() { + let PHASE0 = "profile-change-teardown"; + let PHASE1 = "profile-before-change"; + let PHASE2 = "xpcom-will-shutdown"; + let t0 = Date.now(); + + do_print("Starting shutdown"); + terminator.observe(null, "profile-change-teardown", null); + + do_print("Moving to next phase"); + terminator.observe(null, PHASE1, null); + + let data = yield promiseShutdownDurationData(); + + let t1 = Date.now(); + + Assert.ok(PHASE0 in data, "The file contains the expected key"); + let duration = data[PHASE0]; + Assert.equal(typeof duration, "number"); + Assert.ok(duration >= 0, "Duration is a non-negative number"); + Assert.ok(duration <= Math.ceil((t1 - t0) / 1000) + 1, + "Duration is reasonable"); + + Assert.equal(Object.keys(data).length, 1, "Data does not contain other durations"); + + do_print("Cleaning up and moving to next phase"); + yield File.remove(PATH); + yield File.remove(PATH_TMP); + + do_print("Waiting at least one tick"); + let WAIT_MS = 2000; + yield new Promise(resolve => setTimeout(resolve, WAIT_MS)); + + terminator.observe(null, PHASE2, null); + data = yield promiseShutdownDurationData(); + + let t2 = Date.now(); + + Assert.equal(Object.keys(data).sort().join(", "), + [PHASE0, PHASE1].sort().join(", "), + "The file contains the expected keys"); + Assert.equal(data[PHASE0], duration, "Duration of phase 0 hasn't changed"); + let duration2 = data[PHASE1]; + Assert.equal(typeof duration2, "number"); + Assert.ok(duration2 >= WAIT_MS / 2000, "We have waited at least " + (WAIT_MS / 2000) + " ticks"); + Assert.ok(duration2 <= Math.ceil((t2 - t1) / 1000) + 1, + "Duration is reasonable"); +}); + +function run_test() { + run_next_test(); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_reload.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_reload.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_reload.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/tests/xpcshell/test_terminator_reload.js 2014-11-26 21:46:02.000000000 +0000 @@ -0,0 +1,85 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + + +// Test that the Shutdown Terminator reloads durations correctly + +const Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; + +Cu.import("resource://gre/modules/Services.jsm", this); +Cu.import("resource://gre/modules/osfile.jsm", this); +Cu.import("resource://gre/modules/Timer.jsm", this); +Cu.import("resource://gre/modules/Task.jsm", this); + +let {Path, File, Constants} = OS; + +let PATH; + +let HISTOGRAMS = { + "quit-application": "SHUTDOWN_PHASE_DURATION_TICKS_QUIT_APPLICATION", + "profile-change-teardown": "SHUTDOWN_PHASE_DURATION_TICKS_PROFILE_CHANGE_TEARDOWN", + "profile-before-change": "SHUTDOWN_PHASE_DURATION_TICKS_PROFILE_BEFORE_CHANGE", + "xpcom-will-shutdown": "SHUTDOWN_PHASE_DURATION_TICKS_XPCOM_WILL_SHUTDOWN", +}; + +add_task(function* init() { + do_get_profile(); + PATH = Path.join(Constants.Path.localProfileDir, "ShutdownDuration.json"); +}); + +add_task(function* test_reload() { + do_print("Forging data"); + let data = {}; + let telemetrySnapshots = Services.telemetry.histogramSnapshots; + let i = 0; + for (let k of Object.keys(HISTOGRAMS)) { + let id = HISTOGRAMS[k]; + data[k] = i++; + Assert.equal(telemetrySnapshots[id] || undefined, undefined, "Histogram " + id + " is empty"); + } + + + yield OS.File.writeAtomic(PATH, JSON.stringify(data)); + + const TOPIC = "shutdown-terminator-telemetry-updated"; + + let wait = new Promise(resolve => + Services.obs.addObserver( + function observer() { + do_print("Telemetry has been updated"); + Services.obs.removeObserver(observer, TOPIC); + resolve(); + }, + TOPIC, + false)); + + do_print("Starting nsTerminatorTelemetry"); + let tt = Cc["@mozilla.org/toolkit/shutdown-terminator-telemetry;1"]. + createInstance(Ci.nsIObserver); + tt.observe(null, "profile-after-change", ""); + + do_print("Waiting until telemetry is updated"); + // Now wait until Telemetry is updated + yield wait; + + telemetrySnapshots = Services.telemetry.histogramSnapshots; + for (let k of Object.keys(HISTOGRAMS)) { + let id = HISTOGRAMS[k]; + do_print("Testing histogram " + id); + let snapshot = telemetrySnapshots[id]; + let count = 0; + for (let x of snapshot.counts) { + count += x; + } + Assert.equal(count, 1, "We have added one item"); + } + +}); + +function run_test() { + run_next_test(); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/tests/xpcshell/xpcshell.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/tests/xpcshell/xpcshell.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/terminator/tests/xpcshell/xpcshell.ini 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/terminator/tests/xpcshell/xpcshell.ini 2014-11-26 21:46:02.000000000 +0000 @@ -0,0 +1,7 @@ +[DEFAULT] +head= +tail= + +[test_terminator_record.js] +[test_terminator_reload.js] +skip-if = (os == "android" || appname == "b2g") diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/Classifier.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/Classifier.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/Classifier.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/Classifier.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -11,7 +11,6 @@ #include "nsIInputStream.h" #include "nsISeekableStream.h" #include "nsIFile.h" -#include "nsAutoPtr.h" #include "mozilla/Telemetry.h" #include "prlog.h" @@ -182,19 +181,17 @@ nsTArray tables; ActiveTables(tables); for (uint32_t i = 0; i < tables.Length(); i++) { - nsAutoPtr store(new HashStore(tables[i], mStoreDirectory)); - if (!store) - continue; + HashStore store(tables[i], mStoreDirectory); - nsresult rv = store->Open(); + nsresult rv = store.Open(); if (NS_FAILED(rv)) continue; - aResult.Append(store->TableName()); + aResult.Append(store.TableName()); aResult.Append(';'); - ChunkSet &adds = store->AddChunks(); - ChunkSet &subs = store->SubChunks(); + ChunkSet &adds = store.AddChunks(); + ChunkSet &subs = store.SubChunks(); if (adds.Length() > 0) { aResult.AppendLiteral("a:"); @@ -401,15 +398,13 @@ ScanStoreDir(foundTables); for (uint32_t i = 0; i < foundTables.Length(); i++) { - nsAutoPtr store(new HashStore(nsCString(foundTables[i]), mStoreDirectory)); - if (!store) - return NS_ERROR_OUT_OF_MEMORY; + HashStore store(nsCString(foundTables[i]), mStoreDirectory); - nsresult rv = store->Open(); + nsresult rv = store.Open(); if (NS_FAILED(rv)) continue; - LookupCache *lookupCache = GetLookupCache(store->TableName()); + LookupCache *lookupCache = GetLookupCache(store.TableName()); if (!lookupCache) { continue; } @@ -417,14 +412,14 @@ if (!lookupCache->IsPrimed()) continue; - const ChunkSet &adds = store->AddChunks(); - const ChunkSet &subs = store->SubChunks(); + const ChunkSet &adds = store.AddChunks(); + const ChunkSet &subs = store.SubChunks(); if (adds.Length() == 0 && subs.Length() == 0) continue; - LOG(("Active table: %s", store->TableName().get())); - mActiveTablesCache.AppendElement(store->TableName()); + LOG(("Active table: %s", store.TableName().get())); + mActiveTablesCache.AppendElement(store.TableName()); } return NS_OK; @@ -574,11 +569,7 @@ { LOG(("Classifier::ApplyTableUpdates(%s)", PromiseFlatCString(aTable).get())); - nsAutoPtr store(new HashStore(aTable, mStoreDirectory)); - - if (!store) { - return NS_ERROR_FAILURE; - } + HashStore store(aTable, mStoreDirectory); // take the quick exit if there is no valid update for us // (common case) @@ -586,7 +577,7 @@ for (uint32_t i = 0; i < aUpdates->Length(); i++) { TableUpdate *update = aUpdates->ElementAt(i); - if (!update || !update->TableName().Equals(store->TableName())) + if (!update || !update->TableName().Equals(store.TableName())) continue; if (update->Empty()) { aUpdates->ElementAt(i) = nullptr; @@ -601,20 +592,20 @@ return NS_OK; } - nsresult rv = store->Open(); + nsresult rv = store.Open(); NS_ENSURE_SUCCESS(rv, rv); - rv = store->BeginUpdate(); + rv = store.BeginUpdate(); NS_ENSURE_SUCCESS(rv, rv); // Read the part of the store that is (only) in the cache - LookupCache *prefixSet = GetLookupCache(store->TableName()); + LookupCache *prefixSet = GetLookupCache(store.TableName()); if (!prefixSet) { return NS_ERROR_FAILURE; } - nsTArray AddPrefixHashes; - rv = prefixSet->GetPrefixes(&AddPrefixHashes); + FallibleTArray AddPrefixHashes; + rv = prefixSet->GetPrefixes(AddPrefixHashes); NS_ENSURE_SUCCESS(rv, rv); - rv = store->AugmentAdds(AddPrefixHashes); + rv = store.AugmentAdds(AddPrefixHashes); NS_ENSURE_SUCCESS(rv, rv); AddPrefixHashes.Clear(); @@ -624,15 +615,15 @@ for (uint32_t i = 0; i < aUpdates->Length(); i++) { TableUpdate *update = aUpdates->ElementAt(i); - if (!update || !update->TableName().Equals(store->TableName())) + if (!update || !update->TableName().Equals(store.TableName())) continue; - rv = store->ApplyUpdate(*update); + rv = store.ApplyUpdate(*update); NS_ENSURE_SUCCESS(rv, rv); applied++; - LOG(("Applied update to table %s:", store->TableName().get())); + LOG(("Applied update to table %s:", store.TableName().get())); LOG((" %d add chunks", update->AddChunks().Length())); LOG((" %d add prefixes", update->AddPrefixes().Length())); LOG((" %d add completions", update->AddCompletes().Length())); @@ -657,30 +648,30 @@ delete update; } - LOG(("Applied %d update(s) to %s.", applied, store->TableName().get())); + LOG(("Applied %d update(s) to %s.", applied, store.TableName().get())); - rv = store->Rebuild(); + rv = store.Rebuild(); NS_ENSURE_SUCCESS(rv, rv); // Not an update with Completes, clear all completes data. if (!hasCompletes) { - store->ClearCompletes(); + store.ClearCompletes(); } - LOG(("Table %s now has:", store->TableName().get())); - LOG((" %d add chunks", store->AddChunks().Length())); - LOG((" %d add prefixes", store->AddPrefixes().Length())); - LOG((" %d add completions", store->AddCompletes().Length())); - LOG((" %d sub chunks", store->SubChunks().Length())); - LOG((" %d sub prefixes", store->SubPrefixes().Length())); - LOG((" %d sub completions", store->SubCompletes().Length())); + LOG(("Table %s now has:", store.TableName().get())); + LOG((" %d add chunks", store.AddChunks().Length())); + LOG((" %d add prefixes", store.AddPrefixes().Length())); + LOG((" %d add completions", store.AddCompletes().Length())); + LOG((" %d sub chunks", store.SubChunks().Length())); + LOG((" %d sub prefixes", store.SubPrefixes().Length())); + LOG((" %d sub completions", store.SubCompletes().Length())); - rv = store->WriteFile(); + rv = store.WriteFile(); NS_ENSURE_SUCCESS(rv, rv); // At this point the store is updated and written out to disk, but // the data is still in memory. Build our quick-lookup table here. - rv = prefixSet->Build(store->AddPrefixes(), store->AddCompletes()); + rv = prefixSet->Build(store.AddPrefixes(), store.AddCompletes()); NS_ENSURE_SUCCESS(rv, rv); #if defined(DEBUG) && defined(PR_LOGGING) @@ -691,8 +682,8 @@ if (updateFreshness) { int64_t now = (PR_Now() / PR_USEC_PER_SEC); - LOG(("Successfully updated %s", store->TableName().get())); - mTableFreshness.Put(store->TableName(), now); + LOG(("Successfully updated %s", store.TableName().get())); + mTableFreshness.Put(store.TableName(), now); } return NS_OK; @@ -734,8 +725,8 @@ return NS_ERROR_FAILURE; } - nsTArray prefixes; - nsresult rv = cache->GetPrefixes(&prefixes); + FallibleTArray prefixes; + nsresult rv = cache->GetPrefixes(prefixes); NS_ENSURE_SUCCESS(rv, rv); size_t idx = prefixes.BinaryIndexOf(aPrefix.ToUint32()); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/HashStore.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/HashStore.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/HashStore.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/HashStore.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -30,7 +30,6 @@ #include "HashStore.h" -#include "nsAutoPtr.h" #include "nsICryptoHash.h" #include "nsISeekableStream.h" #include "nsIStreamConverterService.h" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/LookupCache.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/LookupCache.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/LookupCache.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/LookupCache.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -684,24 +684,14 @@ } nsresult -LookupCache::GetPrefixes(nsTArray* aAddPrefixes) +LookupCache::GetPrefixes(FallibleTArray& aAddPrefixes) { if (!mPrimed) { // This can happen if its a new table, so no error. LOG(("GetPrefixes from empty LookupCache")); return NS_OK; } - uint32_t cnt; - uint32_t *arr; - nsresult rv = mPrefixSet->GetPrefixes(&cnt, &arr); - NS_ENSURE_SUCCESS(rv, rv); - bool appendOk = aAddPrefixes->AppendElements(arr, cnt); - nsMemory::Free(arr); - if (appendOk) { - return NS_OK; - } else { - return NS_ERROR_FAILURE; - } + return mPrefixSet->GetPrefixesNative(aAddPrefixes); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/LookupCache.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/LookupCache.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/LookupCache.h 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/LookupCache.h 2014-11-26 21:46:02.000000000 +0000 @@ -9,7 +9,6 @@ #include "Entries.h" #include "nsString.h" #include "nsTArray.h" -#include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsIFile.h" #include "nsIFileStreams.h" @@ -99,7 +98,7 @@ // This will Clear() the passed arrays when done. nsresult Build(AddPrefixArray& aAddPrefixes, AddCompleteArray& aAddCompletes); - nsresult GetPrefixes(nsTArray* aAddPrefixes); + nsresult GetPrefixes(FallibleTArray& aAddPrefixes); void ClearCompleteCache(); #if DEBUG && defined(PR_LOGGING) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js 2014-11-26 21:46:02.000000000 +0000 @@ -176,7 +176,7 @@ this._requests.push({ partialHash: aPartialHash, callback: aCallback, - responses: [], + responses: [] }); }, @@ -223,6 +223,10 @@ let channel = Services.io.newChannelFromURI(uri); channel.loadFlags = loadFlags; + // Disable keepalive. + let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); + httpChannel.setRequestHeader("Connection", "close", false); + this._channel = channel; let body = this.buildRequest(); @@ -365,6 +369,7 @@ request.callback.completionFinished(Cr.NS_OK); } }, + notifyFailure: function HCR_notifyFailure(aStatus) { dump("hashcompleter: notifying failure\n"); for (let i = 0; i < this._requests.length; i++) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -4,7 +4,6 @@ * 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/. */ -#include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsDebug.h" #include "nsPrintfCString.h" @@ -12,13 +11,11 @@ #include "nsString.h" #include "nsUrlClassifierPrefixSet.h" #include "nsIUrlClassifierPrefixSet.h" -#include "nsIRandomGenerator.h" #include "nsIFile.h" #include "nsToolkitCompsCID.h" #include "nsTArray.h" #include "nsThreadUtils.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/Mutex.h" #include "mozilla/Telemetry.h" #include "mozilla/FileUtils.h" #include "prlog.h" @@ -140,18 +137,12 @@ return NS_OK; } -NS_IMETHODIMP -nsUrlClassifierPrefixSet::GetPrefixes(uint32_t* aCount, - uint32_t** aPrefixes) +nsresult +nsUrlClassifierPrefixSet::GetPrefixesNative(FallibleTArray& outArray) { - NS_ENSURE_ARG_POINTER(aCount); - *aCount = 0; - NS_ENSURE_ARG_POINTER(aPrefixes); - *aPrefixes = nullptr; - - uint64_t itemCount = mTotalPrefixes; - uint32_t* prefixArray = static_cast(nsMemory::Alloc(itemCount * sizeof(uint32_t))); - NS_ENSURE_TRUE(prefixArray, NS_ERROR_OUT_OF_MEMORY); + if (!outArray.SetLength(mTotalPrefixes)) { + return NS_ERROR_OUT_OF_MEMORY; + } uint32_t prefixIdxLength = mIndexPrefixes.Length(); uint32_t prefixCnt = 0; @@ -159,14 +150,37 @@ for (uint32_t i = 0; i < prefixIdxLength; i++) { uint32_t prefix = mIndexPrefixes[i]; - prefixArray[prefixCnt++] = prefix; + outArray[prefixCnt++] = prefix; for (uint32_t j = 0; j < mIndexDeltas[i].Length(); j++) { prefix += mIndexDeltas[i][j]; - prefixArray[prefixCnt++] = prefix; + outArray[prefixCnt++] = prefix; } } - NS_ASSERTION(itemCount == prefixCnt, "Lengths are inconsistent"); + NS_ASSERTION(mTotalPrefixes == prefixCnt, "Lengths are inconsistent"); + return NS_OK; +} + +NS_IMETHODIMP +nsUrlClassifierPrefixSet::GetPrefixes(uint32_t* aCount, + uint32_t** aPrefixes) +{ + NS_ENSURE_ARG_POINTER(aCount); + *aCount = 0; + NS_ENSURE_ARG_POINTER(aPrefixes); + *aPrefixes = nullptr; + + FallibleTArray prefixes; + nsresult rv = GetPrefixesNative(prefixes); + if (NS_FAILED(rv)) { + return rv; + } + + uint64_t itemCount = prefixes.Length(); + uint32_t* prefixArray = static_cast(nsMemory::Alloc(itemCount * sizeof(uint32_t))); + NS_ENSURE_TRUE(prefixArray, NS_ERROR_OUT_OF_MEMORY); + + memcpy(prefixArray, prefixes.Elements(), sizeof(uint32_t) * itemCount); *aCount = itemCount; *aPrefixes = prefixArray; @@ -300,7 +314,7 @@ nsTArray indexStarts; indexStarts.SetLength(indexSize); mIndexPrefixes.SetLength(indexSize); - mIndexDeltas.Clear(); + mIndexDeltas.SetLength(indexSize); mTotalPrefixes = indexSize; @@ -313,7 +327,6 @@ return NS_ERROR_FILE_CORRUPTED; } for (uint32_t i = 0; i < indexSize; i++) { - mIndexDeltas.AppendElement(); uint32_t numInDelta = i == indexSize - 1 ? deltaSize - indexStarts[i] : indexStarts[i + 1] - indexStarts[i]; if (numInDelta > 0) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h 2014-11-26 21:46:02.000000000 +0000 @@ -16,8 +16,6 @@ #include "nsTArray.h" #include "nsToolkitCompsCID.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/Mutex.h" -#include "mozilla/CondVar.h" #include "mozilla/FileUtils.h" #include "mozilla/Atomics.h" @@ -36,6 +34,7 @@ NS_IMETHOD LoadFromFile(nsIFile* aFile); NS_IMETHOD StoreToFile(nsIFile* aFile); + nsresult GetPrefixesNative(FallibleTArray& outArray); size_t SizeInMemory() { return mMemoryInUse; }; NS_DECL_THREADSAFE_ISUPPORTS diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -120,17 +120,25 @@ if ((NS_SUCCEEDED(aUpdateUrl->SchemeIs("file", &match)) && match) || (NS_SUCCEEDED(aUpdateUrl->SchemeIs("data", &match)) && match)) { mChannel->SetContentType(NS_LITERAL_CSTRING("application/vnd.google.safebrowsing-update")); + } else { + // We assume everything else is an HTTP request. + + // Disable keepalive. + nsCOMPtr httpChannel = do_QueryInterface(mChannel, &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Connection"), NS_LITERAL_CSTRING("close"), false); + NS_ENSURE_SUCCESS(rv, rv); } - // Create a custom LoadContext for SafeBrowsing, so we can use callbacks on - // the channel to query the appId which allows separation of safebrowsing - // cookies in a separate jar. + // Create a custom LoadContext for SafeBrowsing, so we can use callbacks on + // the channel to query the appId which allows separation of safebrowsing + // cookies in a separate jar. nsCOMPtr sbContext = new mozilla::LoadContext(NECKO_SAFEBROWSING_APP_ID); rv = mChannel->SetNotificationCallbacks(sbContext); NS_ENSURE_SUCCESS(rv, rv); - // Make the request + // Make the request. rv = mChannel->AsyncOpen(this, nullptr); NS_ENSURE_SUCCESS(rv, rv); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/ProtocolParser.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/ProtocolParser.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/ProtocolParser.cpp 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/ProtocolParser.cpp 2014-11-26 21:46:02.000000000 +0000 @@ -284,7 +284,7 @@ // Pull the chunk out of the pending stream data. nsAutoCString chunk; chunk.Assign(Substring(mPending, 0, mChunkState.length)); - mPending = Substring(mPending, mChunkState.length); + mPending.Cut(0, mChunkState.length); *aDone = false; mState = PROTOCOL_STATE_CONTROL; @@ -590,14 +590,14 @@ } bool -ProtocolParser::NextLine(nsACString& line) +ProtocolParser::NextLine(nsACString& aLine) { int32_t newline = mPending.FindChar('\n'); if (newline == kNotFound) { return false; } - line.Assign(Substring(mPending, 0, newline)); - mPending = Substring(mPending, newline + 1); + aLine.Assign(Substring(mPending, 0, newline)); + mPending.Cut(0, newline + 1); return true; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/tests/unit/test_hashcompleter.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/tests/unit/test_hashcompleter.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/url-classifier/tests/unit/test_hashcompleter.js 2014-11-14 09:37:30.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/url-classifier/tests/unit/test_hashcompleter.js 2014-11-26 21:46:02.000000000 +0000 @@ -220,8 +220,8 @@ server = new HttpServer(); server.registerPathHandler(SERVER_PATH, hashCompleterServer); - const SERVER_PORT = 8080; - server.start(SERVER_PORT); + server.start(-1); + const SERVER_PORT = server.identity.primaryPort; gethashUrl = "http://localhost:" + SERVER_PORT + SERVER_PATH; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/viewsource/test/test_428653.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/viewsource/test/test_428653.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/toolkit/components/viewsource/test/test_428653.xul 2014-11-14 09:37:31.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/toolkit/components/viewsource/test/test_428653.xul 2014-11-26 21:46:02.000000000 +0000 @@ -17,8 +17,9 @@ \n"; + print "\n\n"; + print "\n"; + if ($source) { + print "

"; + print quoteHTML "\n"; + print quoteHTML "\n"; + print quoteHTML "\n"; + print "\n"; + print quoteHTML "\n\n"; + print quoteHTML "\n"; + print "\n"; + print quoteHTML "\n"; + print quoteHTML "\n"; + print "

\n"; + } else { + print "\n"; + } + print "\n"; + print "\n"; +} + + + +# Read the bloat file into hash table $h. The hash table is indexed by class names; +# each entry is a list with the following elements: +# bytesAlloc Total number of bytes allocated +# bytesNet Total number of bytes allocated but not deallocated +# objectsAlloc Total number of objects allocated +# objectsNet Total number of objects allocated but not deallocated +# refsAlloc Total number of references AddRef'd +# refsNet Total number of references AddRef'd but not Released +# Except for TOTAL, all hash table entries refer to mutually exclusive data. +# $sizes is a hash table indexed by class names. Each entry of that table contains the class's instance size. +sub readBloatFile($\%\%) { + my ($file, $h, $sizes) = @_; + local $_; # Needed for 'while ()' below. + + my $readSomething = 0; + open FILE, $file; + while () { + if (my ($name, $size, $bytesNet, $objectsAlloc, $objectsNet, $refsAlloc, $refsNet) = + /^\s*(?:\d+)\s+([\w:]+)\s+(\d+)\s+(-?\d+)\s+(\d+)\s+(-?\d+)\s*\([^()]*\)\s*(\d+)\s+(-?\d+)\s*\([^()]*\)\s*$/) { + my $bytesAlloc; + if ($name eq "TOTAL") { + $size = "undefined"; + $bytesAlloc = "undefined"; + } else { + $bytesAlloc = $objectsAlloc * $size; + if ($bytesNet != $objectsNet * $size) { + print STDERR "In '$file', class $name bytesNet != objectsNet * size: $bytesNet != $objectsNet * $size\n"; + } + } + print STDERR "Duplicate entry $name in '$file'\n" if $$h{$name}; + $$h{$name} = [$bytesAlloc, $bytesNet, $objectsAlloc, $objectsNet, $refsAlloc, $refsNet]; + + my $oldSize = $$sizes{$name}; + print STDERR "Mismatch of sizes of class $name: $oldSize and $size\n" if defined($oldSize) && $size ne $oldSize; + $$sizes{$name} = $size; + $readSomething = 1; + } elsif (/^\s*(?:\d+)\s+([\w:]+)\s/) { + print STDERR "Unable to parse '$file' line: $_"; + } + } + close FILE; + print STDERR "No data in '$file'\n" unless $readSomething; + return $h; +} + + +my %sizes; # => +my %tables; # => ; see readBloatFile for format of + +# Generate the JavaScript source code for the row named $c. $l can contain the initial entries of the row. +sub genTableRowSource($$) { + my ($l, $c) = @_; + my $lastE; + foreach (@ARGV) { + my $e = $tables{$_}{$c}; + if (defined($lastE) && !defined($e)) { + $e = [0,0,0,0,0,0]; + print STDERR "Class $c is defined in an earlier file but not in '$_'\n"; + } + if (defined $e) { + if (defined $lastE) { + for (my $i = 0; $i <= $#$e; $i++) { + my $n = $$e[$i]; + $l .= ($n eq "undefined" ? "undefined" : $n - $$lastE[$i]) . ","; + } + $l .= " "; + } else { + $l .= join(",", @$e) . ", "; + } + $lastE = $e; + } else { + $l .= "0,0,0,0,0,0, "; + } + } + $l .= join(",", @$lastE); + return "[$l]"; +} + + + +my $debug; +my $source; +my $showMode; +my $sortColumn; +my @modeOptions; + +GetOptions("debug" => \$debug, "source" => \$source, "byte=i" => \$modeOptions[0], "obj=i" => \$modeOptions[1], "ref=i" => \$modeOptions[2]); +for (my $i = 0; $i != 3; $i++) { + my $modeOption = $modeOptions[$i]; + if ($modeOption) { + die "Only one of -byte, -obj, or -ref may be given" if defined $showMode; + my $nFileColumns = scalar(@ARGV) + 1; + die "-byte, -obj, or -ref column number out of range" if $modeOption < 0 || $modeOption >= 2 + 2*$nFileColumns; + $showMode = $i; + if ($modeOption >= 2) { + $modeOption -= 2; + $sortColumn = 2 + $showMode*2; + if ($modeOption >= $nFileColumns) { + $sortColumn++; + $modeOption -= $nFileColumns; + } + $sortColumn += $modeOption*6; + } else { + $sortColumn = $modeOption; + } + } +} +unless (defined $showMode) { + $showMode = 0; + $sortColumn = 0; +} + +# Read all of the bloat files. +foreach (@ARGV) { + unless ($tables{$_}) { + my $f = $_; + my %table; + + readBloatFile $_, %table, %sizes; + $tables{$_} = \%table; + } +} +die "No input" unless %sizes; + +my @scriptData; # JavaScript source for the tables passed to JavaScript. Each entry is one line of JavaScript. +my @persistentScriptData; # Same as @scriptData, but persists the page reloads itself. + +# Print a list of bloat file names. +push @persistentScriptData, "var nFiles = " . scalar(@ARGV) . ";"; +push @persistentScriptData, "var fileTags = [" . join(", ", map {singleQuoteString substr(fileCoreName($_), -10)} @ARGV) . "];"; +push @persistentScriptData, "var fileNames = [" . join(", ", map {singleQuoteString $_} @ARGV) . "];"; +push @persistentScriptData, "var fileDates = [" . join(", ", map {singleQuoteString localtime fileModDate $_} @ARGV) . "];"; + +# Print the bloat tables. +push @persistentScriptData, "var totals = " . genTableRowSource('"TOTAL", undefined, ', "TOTAL") . ";"; +push @scriptData, "var classTables = ["; +delete $sizes{"TOTAL"}; +my @classes = sort(keys %sizes); +for (my $i = 0; $i <= $#classes; $i++) { + my $c = $classes[$i]; + push @scriptData, genTableRowSource(doubleQuoteString($c).", ".$sizes{$c}.", ", $c) . ($i == $#classes ? "];" : ","); +} + +generate(@scriptData, @persistentScriptData, $debug, $source, $showMode, $sortColumn); +1; + + +# The source of the eval'd JavaScript follows. +# Comments starting with // that are alone on a line are stripped by the Perl script. +__END__ + +// showMode: 0=bytes, 1=objects, 2=references +var showMode; +var modeName; +var modeNameUpper; + +var sortColumn; + +// Sort according to the sortColumn. Column 0 is sorted alphabetically in ascending order. +// All other columns are sorted numerically in descending order, with column 0 used for a secondary sort. +// Undefined is always listed last. +function sortCompare(x, y) { + if (sortColumn) { + var xc = x[sortColumn]; + var yc = y[sortColumn]; + if (xc < yc || xc === undefined && yc !== undefined) return 1; + if (yc < xc || yc === undefined && xc !== undefined) return -1; + } + + var x0 = x[0]; + var y0 = y[0]; + if (x0 > y0 || x0 === undefined && y0 !== undefined) return 1; + if (y0 > x0 || y0 === undefined && x0 !== undefined) return -1; + return 0; +} + + +// Quote special HTML characters in the string. +function quoteHTML(s) { + s = s.replace(/&/g, '&'); + // Can't use //g, '>'); + s = s.replace(/ /g, ' '); + return s; +} + + +function writeFileTable(d) { + d.writeln(''); + d.writeln('\n\n\n\n'); + for (var i = 0; i < nFiles; i++) + d.writeln('\n\n\n\n'); + d.writeln('
NameFileDate
'+quoteHTML(fileTags[i])+''+quoteHTML(fileNames[i])+''+quoteHTML(fileDates[i])+'
'); +} + + +function writeReloadLink(d, column, s, rowspan) { + d.write(rowspan == 1 ? '' : ''); + if (column != sortColumn) + d.write(''); + d.write(s); + if (column != sortColumn) + d.write(''); + d.writeln(''); +} + +function writeClassTableRow(d, row, base, modeName) { + if (modeName) { + d.writeln('\n'+modeName+''); + } else { + d.writeln('\n'+quoteHTML(row[0])+''); + var v = row[1]; + d.writeln(''+(v === undefined ? '' : v)+''); + } + for (var i = 0; i != 2; i++) { + var c = base + i; + for (var j = 0; j <= nFiles; j++) { + v = row[c]; + var style = 'num'; + if (j != nFiles) + if (v > 0) { + style = 'pos'; + v = '+'+v; + } else + style = 'neg'; + d.writeln(''+(v === undefined ? '' : v)+''); + c += 6; + } + } + d.writeln(''); +} + +function writeClassTable(d) { + var base = 2 + showMode*2; + + // Make a copy because a sort is destructive. + var table = classTables.concat(); + table.sort(sortCompare); + + d.writeln(''); + + d.writeln(''); + writeReloadLink(d, 0, 'Class Name', 2); + writeReloadLink(d, 1, 'Instance
Size', 2); + d.writeln(''); + d.writeln('\n'); + d.writeln(''); + for (var i = 0; i != 2; i++) { + var c = base + i; + for (var j = 0; j <= nFiles; j++) { + writeReloadLink(d, c, j == nFiles ? 'Total' : quoteHTML(fileTags[j]), 1); + c += 6; + } + } + d.writeln(''); + + writeClassTableRow(d, totals, base, 0); + for (var r = 0; r < table.length; r++) + writeClassTableRow(d, table[r], base, 0); + + d.writeln('
'+modeNameUpper+'s allocated'+modeNameUpper+'s allocated but not freed
'); +} + + +var modeNames = ["byte", "object", "reference"]; +var modeNamesUpper = ["Byte", "Object", "Reference"]; +var styleSheet = ''; + + +function showHead(d) { + modeName = modeNames[showMode]; + modeNameUpper = modeNamesUpper[showMode]; + d.writeln(''+modeNameUpper+' Bloats'); + d.writeln(styleSheet); +} + +function showBody(d) { + d.writeln('

'+modeNameUpper+' Bloats

'); + writeFileTable(d); + d.write(''); + for (var i = 0; i != 3; i++) + if (i != showMode) { + var newSortColumn = sortColumn; + if (sortColumn >= 2) + newSortColumn = sortColumn + (i-showMode)*2; + d.write(''); + } + d.writeln(''); + d.writeln('

The numbers do not include malloc\'d data such as string contents.

'); + d.writeln('

Click on a column heading to sort by that column. Click on a class name to see details for that class.

'); + writeClassTable(d); +} + + +function showRowDetail(rowName) { + var row; + var i; + + if (rowName == "TOTAL") + row = totals; + else { + for (i = 0; i < classTables.length; i++) + if (rowName == classTables[i][0]) { + row = classTables[i]; + break; + } + } + if (row) { + var w = window.open("", "ClassTableRowDetails"); + var d = w.document; + d.open(); + d.writeln(''); + d.writeln('\n\n'+quoteHTML(rowName)+' bloat details'); + d.writeln(styleSheet); + d.writeln('\n\n'); + d.writeln('

'+quoteHTML(rowName)+'

'); + if (row[1] !== undefined) + d.writeln('

Each instance has '+row[1]+' bytes.

'); + + d.writeln(''); + d.writeln('\n\n'); + d.writeln('\n'); + d.writeln('\n'); + for (i = 0; i != 2; i++) + for (var j = 0; j <= nFiles; j++) + d.writeln(''); + d.writeln(''); + + for (i = 0; i != 3; i++) + writeClassTableRow(d, row, 2+i*2, modeNamesUpper[i]+'s'); + + d.writeln('
AllocatedAllocated but not freed
'+(j == nFiles ? 'Total' : quoteHTML(fileTags[j]))+'
\n\n'); + d.close(); + } + return undefined; +} + + +function stringSource(s) { + s = s.replace(/\\/g, '\\\\'); + s = s.replace(/"/g, '\\"'); + s = s.replace(/<\//g, '<\\/'); + return '"'+s+'"'; +} + +function reloadSelf(n,m) { + // Need to cache these because globals go away on document.open(). + var sa = srcArray; + var ss = stringSource; + var ct = classTables; + var i; + + document.open(); + // Uncomment this and comment the document.open() line above to see the reloaded page's source. + //var w = window.open("", "NewDoc"); + //var d = w.document; + //var document = new Object; + //document.write = function () { + // for (var i = 0; i < arguments.length; i++) { + // var s = arguments[i].toString(); + // s = s.replace(/&/g, '&'); + // s = s.replace(/\x3C/g, '<'); + // s = s.replace(/>/g, '>'); + // s = s.replace(/ /g, ' '); + // d.write(s); + // } + //}; + //document.writeln = function () { + // for (var i = 0; i < arguments.length; i++) { + // var s = arguments[i].toString(); + // s = s.replace(/&/g, '&'); + // s = s.replace(/\x3C/g, '<'); + // s = s.replace(/>/g, '>'); + // s = s.replace(/ /g, ' '); + // d.write(s); + // } + // d.writeln('
'); + //}; + + document.writeln(''); + document.writeln('\n\n\n\n\n\n\n\n'); + document.close(); + return undefined; +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mach_commands.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mach_commands.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mach_commands.py 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mach_commands.py 2014-11-26 21:46:05.000000000 +0000 @@ -293,25 +293,6 @@ @CommandProvider -class ReviewboardToolsProvider(MachCommandBase): - @Command('rbt', category='devenv', - description='Run Reviewboard Tools') - @CommandArgument('args', nargs='...', help='Arguments to rbt tool') - def rbt(self, args): - if not args: - args = ['help'] - - self._activate_virtualenv() - self.virtualenv_manager.install_pip_package('RBTools==0.6') - - from rbtools.commands.main import main - - # main() doesn't accept arguments and instead reads from sys.argv. So, - # we fake it out. - sys.argv = ['rbt'] + args - return main() - -@CommandProvider class FormatProvider(MachCommandBase): @Command('clang-format', category='misc', description='Run clang-format on current changes') diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/memory/bloattable.pl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/memory/bloattable.pl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/memory/bloattable.pl 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/memory/bloattable.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,590 +0,0 @@ -#!/usr/bin/perl -w -# -# 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/. - -# bloattable [-debug] [-source] [-byte n|-obj n|-ref n] ... > -# -# file1, file2, ... filen should be successive BloatView files generated from the same run. -# Summarize them in an HTML table. Output the HTML to the standard output. -# -# If -debug is set, create a slightly larger html file which is more suitable for debugging this script. -# If -source is set, create an html file that prints the html source as the output -# If -byte n, -obj n, or -ref n is given, make the page default to showing byte, object, or reference statistics, -# respectively, and sort by the nth column (n is zero-based, so the first column has n==0). -# -# See http://lxr.mozilla.org/mozilla/source/xpcom/doc/MemoryTools.html - -use 5.004; -use strict; -use diagnostics; -use File::Basename; -use Getopt::Long; - -# The generated HTML is almost entirely generated by a script. Only the , , and elements are explicit -# because a \n"; - print "\n\n"; - print "\n"; - if ($source) { - print "

"; - print quoteHTML "\n"; - print quoteHTML "\n"; - print quoteHTML "\n"; - print "\n"; - print quoteHTML "\n\n"; - print quoteHTML "\n"; - print "\n"; - print quoteHTML "\n"; - print quoteHTML "\n"; - print "

\n"; - } else { - print "\n"; - } - print "\n"; - print "\n"; -} - - - -# Read the bloat file into hash table $h. The hash table is indexed by class names; -# each entry is a list with the following elements: -# bytesAlloc Total number of bytes allocated -# bytesNet Total number of bytes allocated but not deallocated -# objectsAlloc Total number of objects allocated -# objectsNet Total number of objects allocated but not deallocated -# refsAlloc Total number of references AddRef'd -# refsNet Total number of references AddRef'd but not Released -# Except for TOTAL, all hash table entries refer to mutually exclusive data. -# $sizes is a hash table indexed by class names. Each entry of that table contains the class's instance size. -sub readBloatFile($\%\%) { - my ($file, $h, $sizes) = @_; - local $_; # Needed for 'while ()' below. - - my $readSomething = 0; - open FILE, $file; - while () { - if (my ($name, $size, $bytesNet, $objectsAlloc, $objectsNet, $refsAlloc, $refsNet) = - /^\s*(?:\d+)\s+([\w:]+)\s+(\d+)\s+(-?\d+)\s+(\d+)\s+(-?\d+)\s*\([^()]*\)\s*(\d+)\s+(-?\d+)\s*\([^()]*\)\s*$/) { - my $bytesAlloc; - if ($name eq "TOTAL") { - $size = "undefined"; - $bytesAlloc = "undefined"; - } else { - $bytesAlloc = $objectsAlloc * $size; - if ($bytesNet != $objectsNet * $size) { - print STDERR "In '$file', class $name bytesNet != objectsNet * size: $bytesNet != $objectsNet * $size\n"; - } - } - print STDERR "Duplicate entry $name in '$file'\n" if $$h{$name}; - $$h{$name} = [$bytesAlloc, $bytesNet, $objectsAlloc, $objectsNet, $refsAlloc, $refsNet]; - - my $oldSize = $$sizes{$name}; - print STDERR "Mismatch of sizes of class $name: $oldSize and $size\n" if defined($oldSize) && $size ne $oldSize; - $$sizes{$name} = $size; - $readSomething = 1; - } elsif (/^\s*(?:\d+)\s+([\w:]+)\s/) { - print STDERR "Unable to parse '$file' line: $_"; - } - } - close FILE; - print STDERR "No data in '$file'\n" unless $readSomething; - return $h; -} - - -my %sizes; # => -my %tables; # => ; see readBloatFile for format of - -# Generate the JavaScript source code for the row named $c. $l can contain the initial entries of the row. -sub genTableRowSource($$) { - my ($l, $c) = @_; - my $lastE; - foreach (@ARGV) { - my $e = $tables{$_}{$c}; - if (defined($lastE) && !defined($e)) { - $e = [0,0,0,0,0,0]; - print STDERR "Class $c is defined in an earlier file but not in '$_'\n"; - } - if (defined $e) { - if (defined $lastE) { - for (my $i = 0; $i <= $#$e; $i++) { - my $n = $$e[$i]; - $l .= ($n eq "undefined" ? "undefined" : $n - $$lastE[$i]) . ","; - } - $l .= " "; - } else { - $l .= join(",", @$e) . ", "; - } - $lastE = $e; - } else { - $l .= "0,0,0,0,0,0, "; - } - } - $l .= join(",", @$lastE); - return "[$l]"; -} - - - -my $debug; -my $source; -my $showMode; -my $sortColumn; -my @modeOptions; - -GetOptions("debug" => \$debug, "source" => \$source, "byte=i" => \$modeOptions[0], "obj=i" => \$modeOptions[1], "ref=i" => \$modeOptions[2]); -for (my $i = 0; $i != 3; $i++) { - my $modeOption = $modeOptions[$i]; - if ($modeOption) { - die "Only one of -byte, -obj, or -ref may be given" if defined $showMode; - my $nFileColumns = scalar(@ARGV) + 1; - die "-byte, -obj, or -ref column number out of range" if $modeOption < 0 || $modeOption >= 2 + 2*$nFileColumns; - $showMode = $i; - if ($modeOption >= 2) { - $modeOption -= 2; - $sortColumn = 2 + $showMode*2; - if ($modeOption >= $nFileColumns) { - $sortColumn++; - $modeOption -= $nFileColumns; - } - $sortColumn += $modeOption*6; - } else { - $sortColumn = $modeOption; - } - } -} -unless (defined $showMode) { - $showMode = 0; - $sortColumn = 0; -} - -# Read all of the bloat files. -foreach (@ARGV) { - unless ($tables{$_}) { - my $f = $_; - my %table; - - readBloatFile $_, %table, %sizes; - $tables{$_} = \%table; - } -} -die "No input" unless %sizes; - -my @scriptData; # JavaScript source for the tables passed to JavaScript. Each entry is one line of JavaScript. -my @persistentScriptData; # Same as @scriptData, but persists the page reloads itself. - -# Print a list of bloat file names. -push @persistentScriptData, "var nFiles = " . scalar(@ARGV) . ";"; -push @persistentScriptData, "var fileTags = [" . join(", ", map {singleQuoteString substr(fileCoreName($_), -10)} @ARGV) . "];"; -push @persistentScriptData, "var fileNames = [" . join(", ", map {singleQuoteString $_} @ARGV) . "];"; -push @persistentScriptData, "var fileDates = [" . join(", ", map {singleQuoteString localtime fileModDate $_} @ARGV) . "];"; - -# Print the bloat tables. -push @persistentScriptData, "var totals = " . genTableRowSource('"TOTAL", undefined, ', "TOTAL") . ";"; -push @scriptData, "var classTables = ["; -delete $sizes{"TOTAL"}; -my @classes = sort(keys %sizes); -for (my $i = 0; $i <= $#classes; $i++) { - my $c = $classes[$i]; - push @scriptData, genTableRowSource(doubleQuoteString($c).", ".$sizes{$c}.", ", $c) . ($i == $#classes ? "];" : ","); -} - -generate(@scriptData, @persistentScriptData, $debug, $source, $showMode, $sortColumn); -1; - - -# The source of the eval'd JavaScript follows. -# Comments starting with // that are alone on a line are stripped by the Perl script. -__END__ - -// showMode: 0=bytes, 1=objects, 2=references -var showMode; -var modeName; -var modeNameUpper; - -var sortColumn; - -// Sort according to the sortColumn. Column 0 is sorted alphabetically in ascending order. -// All other columns are sorted numerically in descending order, with column 0 used for a secondary sort. -// Undefined is always listed last. -function sortCompare(x, y) { - if (sortColumn) { - var xc = x[sortColumn]; - var yc = y[sortColumn]; - if (xc < yc || xc === undefined && yc !== undefined) return 1; - if (yc < xc || yc === undefined && xc !== undefined) return -1; - } - - var x0 = x[0]; - var y0 = y[0]; - if (x0 > y0 || x0 === undefined && y0 !== undefined) return 1; - if (y0 > x0 || y0 === undefined && x0 !== undefined) return -1; - return 0; -} - - -// Quote special HTML characters in the string. -function quoteHTML(s) { - s = s.replace(/&/g, '&'); - // Can't use //g, '>'); - s = s.replace(/ /g, ' '); - return s; -} - - -function writeFileTable(d) { - d.writeln(''); - d.writeln('\n\n\n\n'); - for (var i = 0; i < nFiles; i++) - d.writeln('\n\n\n\n'); - d.writeln('
NameFileDate
'+quoteHTML(fileTags[i])+''+quoteHTML(fileNames[i])+''+quoteHTML(fileDates[i])+'
'); -} - - -function writeReloadLink(d, column, s, rowspan) { - d.write(rowspan == 1 ? '' : ''); - if (column != sortColumn) - d.write(''); - d.write(s); - if (column != sortColumn) - d.write(''); - d.writeln(''); -} - -function writeClassTableRow(d, row, base, modeName) { - if (modeName) { - d.writeln('\n'+modeName+''); - } else { - d.writeln('\n'+quoteHTML(row[0])+''); - var v = row[1]; - d.writeln(''+(v === undefined ? '' : v)+''); - } - for (var i = 0; i != 2; i++) { - var c = base + i; - for (var j = 0; j <= nFiles; j++) { - v = row[c]; - var style = 'num'; - if (j != nFiles) - if (v > 0) { - style = 'pos'; - v = '+'+v; - } else - style = 'neg'; - d.writeln(''+(v === undefined ? '' : v)+''); - c += 6; - } - } - d.writeln(''); -} - -function writeClassTable(d) { - var base = 2 + showMode*2; - - // Make a copy because a sort is destructive. - var table = classTables.concat(); - table.sort(sortCompare); - - d.writeln(''); - - d.writeln(''); - writeReloadLink(d, 0, 'Class Name', 2); - writeReloadLink(d, 1, 'Instance
Size', 2); - d.writeln(''); - d.writeln('\n'); - d.writeln(''); - for (var i = 0; i != 2; i++) { - var c = base + i; - for (var j = 0; j <= nFiles; j++) { - writeReloadLink(d, c, j == nFiles ? 'Total' : quoteHTML(fileTags[j]), 1); - c += 6; - } - } - d.writeln(''); - - writeClassTableRow(d, totals, base, 0); - for (var r = 0; r < table.length; r++) - writeClassTableRow(d, table[r], base, 0); - - d.writeln('
'+modeNameUpper+'s allocated'+modeNameUpper+'s allocated but not freed
'); -} - - -var modeNames = ["byte", "object", "reference"]; -var modeNamesUpper = ["Byte", "Object", "Reference"]; -var styleSheet = ''; - - -function showHead(d) { - modeName = modeNames[showMode]; - modeNameUpper = modeNamesUpper[showMode]; - d.writeln(''+modeNameUpper+' Bloats'); - d.writeln(styleSheet); -} - -function showBody(d) { - d.writeln('

'+modeNameUpper+' Bloats

'); - writeFileTable(d); - d.write('
'); - for (var i = 0; i != 3; i++) - if (i != showMode) { - var newSortColumn = sortColumn; - if (sortColumn >= 2) - newSortColumn = sortColumn + (i-showMode)*2; - d.write(''); - } - d.writeln('
'); - d.writeln('

The numbers do not include malloc\'d data such as string contents.

'); - d.writeln('

Click on a column heading to sort by that column. Click on a class name to see details for that class.

'); - writeClassTable(d); -} - - -function showRowDetail(rowName) { - var row; - var i; - - if (rowName == "TOTAL") - row = totals; - else { - for (i = 0; i < classTables.length; i++) - if (rowName == classTables[i][0]) { - row = classTables[i]; - break; - } - } - if (row) { - var w = window.open("", "ClassTableRowDetails"); - var d = w.document; - d.open(); - d.writeln(''); - d.writeln('\n\n'+quoteHTML(rowName)+' bloat details'); - d.writeln(styleSheet); - d.writeln('\n\n'); - d.writeln('

'+quoteHTML(rowName)+'

'); - if (row[1] !== undefined) - d.writeln('

Each instance has '+row[1]+' bytes.

'); - - d.writeln(''); - d.writeln('\n\n'); - d.writeln('\n'); - d.writeln('\n'); - for (i = 0; i != 2; i++) - for (var j = 0; j <= nFiles; j++) - d.writeln(''); - d.writeln(''); - - for (i = 0; i != 3; i++) - writeClassTableRow(d, row, 2+i*2, modeNamesUpper[i]+'s'); - - d.writeln('
AllocatedAllocated but not freed
'+(j == nFiles ? 'Total' : quoteHTML(fileTags[j]))+'
\n\n'); - d.close(); - } - return undefined; -} - - -function stringSource(s) { - s = s.replace(/\\/g, '\\\\'); - s = s.replace(/"/g, '\\"'); - s = s.replace(/<\//g, '<\\/'); - return '"'+s+'"'; -} - -function reloadSelf(n,m) { - // Need to cache these because globals go away on document.open(). - var sa = srcArray; - var ss = stringSource; - var ct = classTables; - var i; - - document.open(); - // Uncomment this and comment the document.open() line above to see the reloaded page's source. - //var w = window.open("", "NewDoc"); - //var d = w.document; - //var document = new Object; - //document.write = function () { - // for (var i = 0; i < arguments.length; i++) { - // var s = arguments[i].toString(); - // s = s.replace(/&/g, '&'); - // s = s.replace(/\x3C/g, '<'); - // s = s.replace(/>/g, '>'); - // s = s.replace(/ /g, ' '); - // d.write(s); - // } - //}; - //document.writeln = function () { - // for (var i = 0; i < arguments.length; i++) { - // var s = arguments[i].toString(); - // s = s.replace(/&/g, '&'); - // s = s.replace(/\x3C/g, '<'); - // s = s.replace(/>/g, '>'); - // s = s.replace(/ /g, ' '); - // d.write(s); - // } - // d.writeln('
'); - //}; - - document.writeln(''); - document.writeln('\n\n\n\n\n\n\n\n'); - document.close(); - return undefined; -} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mercurial/hgsetup/update.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mercurial/hgsetup/update.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mercurial/hgsetup/update.py 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mercurial/hgsetup/update.py 2014-11-26 21:46:05.000000000 +0000 @@ -0,0 +1,93 @@ +# 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/. + +from __future__ import unicode_literals + +import errno +import os +import which + +from configobj import ConfigObjError + +from mozversioncontrol.repoupdate import update_mercurial_repo + +from .config import ( + HgIncludeException, + MercurialConfig, + HOST_FINGERPRINTS, +) + +FINISHED = ''' +Your Mercurial recommended extensions are now up to date! +'''.lstrip() + + +class MercurialUpdater(object): + + def __init__(self, state_dir): + self.state_dir = os.path.normpath(state_dir) + self.ext_dir = os.path.join(self.state_dir, 'mercurial', 'extensions') + self.vcs_tools_dir = os.path.join(self.state_dir, 'version-control-tools') + + def update_all(self, config_paths): + try: + os.makedirs(self.ext_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + try: + hg = which.which('hg') + except which.WhichError as e: + print(e) + print('Try running |mach bootstrap| to ensure your environment is ' + 'up to date.') + return 1 + + try: + c = MercurialConfig(config_paths) + except ConfigObjError as e: + print('Error importing existing Mercurial config!\n') + for error in e.errors: + print(error.message) + + return 1 + except HgIncludeException as e: + print(e.message) + + return 1 + + if 'mqext' in c.extensions: + self.update_mercurial_repo( + hg, + 'https://bitbucket.org/sfink/mqext', + os.path.join(self.ext_dir, 'mqext'), + 'default', + 'Ensuring mqext is up to date...') + + if os.path.isdir(self.vcs_tools_dir): + self.update_mercurial_repo( + hg, + 'https://hg.mozilla.org/hgcustom/version-control-tools', + self.vcs_tools_dir, + 'default', + 'Ensuring version-control-tools is up to date...') + print(FINISHED) + return 0 + + def update_mercurial_repo(self, hg, url, dest, branch, msg): + # We always pass the host fingerprints that we "know" to be canonical + # because the existing config may have outdated fingerprints and this + # may cause Mercurial to abort. + return self._update_repo(hg, url, dest, branch, msg, + update_mercurial_repo, hostfingerprints=HOST_FINGERPRINTS) + + def _update_repo(self, binary, url, dest, branch, msg, fn, *args, **kwargs): + print('=' * 80) + print(msg) + try: + fn(binary, url, dest, branch, *args, **kwargs) + finally: + print('=' * 80) + print('') diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mercurial/hgsetup/wizard.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mercurial/hgsetup/wizard.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mercurial/hgsetup/wizard.py 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mercurial/hgsetup/wizard.py 2014-11-26 21:46:05.000000000 +0000 @@ -17,14 +17,10 @@ from StringIO import StringIO from mozversioncontrol import get_hg_version -from mozversioncontrol.repoupdate import ( - update_mercurial_repo, - update_git_repo, -) +from .update import MercurialUpdater from .config import ( HgIncludeException, - HOST_FINGERPRINTS, MercurialConfig, ) @@ -172,6 +168,7 @@ self.ext_dir = os.path.join(self.state_dir, 'mercurial', 'extensions') self.vcs_tools_dir = os.path.join(self.state_dir, 'version-control-tools') self.update_vcs_tools = False + self.updater = MercurialUpdater(state_dir) def run(self, config_paths): try: @@ -282,7 +279,7 @@ os.path.join(self.ext_dir, 'mqext')) if 'mqext' in c.extensions: - self.update_mercurial_repo( + self.updater.update_mercurial_repo( hg, 'https://bitbucket.org/sfink/mqext', os.path.join(self.ext_dir, 'mqext'), @@ -323,7 +320,7 @@ c.set_bugzilla_credentials(bzuser, bzpass) if self.update_vcs_tools: - self.update_mercurial_repo( + self.updater.update_mercurial_repo( hg, 'https://hg.mozilla.org/hgcustom/version-control-tools', self.vcs_tools_dir, @@ -402,25 +399,6 @@ self.update_vcs_tools = True c.activate_extension(name, path) - def update_mercurial_repo(self, hg, url, dest, branch, msg): - # We always pass the host fingerprints that we "know" to be canonical - # because the existing config may have outdated fingerprints and this - # may cause Mercurial to abort. - return self._update_repo(hg, url, dest, branch, msg, - update_mercurial_repo, hostfingerprints=HOST_FINGERPRINTS) - - def update_git_repo(self, git, url, dest, ref, msg): - return self._update_repo(git, url, dest, ref, msg, update_git_repo) - - def _update_repo(self, binary, url, dest, branch, msg, fn, *args, **kwargs): - print('=' * 80) - print(msg) - try: - fn(binary, url, dest, branch, *args, **kwargs) - finally: - print('=' * 80) - print('') - def _prompt(self, msg, allow_empty=False): print(msg) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mercurial/mach_commands.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mercurial/mach_commands.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/mercurial/mach_commands.py 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/mercurial/mach_commands.py 2014-11-26 21:46:05.000000000 +0000 @@ -9,6 +9,7 @@ from mach.decorators import ( CommandProvider, + CommandArgument, Command, ) @@ -20,16 +21,25 @@ @Command('mercurial-setup', category='devenv', description='Help configure Mercurial for optimal development.') - def mercurial_bootstrap(self): + @CommandArgument('-u', '--update-only', action='store_true', + help='Only update recommended extensions, don\'t run the wizard.') + def mercurial_bootstrap(self, update_only=False): sys.path.append(os.path.dirname(__file__)) - from hgsetup.wizard import MercurialSetupWizard - wizard = MercurialSetupWizard(self._context.state_dir) config_paths = ['~/.hgrc'] if sys.platform in ('win32', 'cygwin'): - config_paths.insert(0, '~/mercurial.ini') - result = wizard.run(map(os.path.expanduser, config_paths)) + config_paths.insert(0, '~/mercurial.ini') + config_paths = map(os.path.expanduser, config_paths) + + if update_only: + from hgsetup.update import MercurialUpdater + updater = MercurialUpdater(self._context.state_dir) + result = updater.update_all(map(os.path.expanduser, config_paths)) + else: + from hgsetup.wizard import MercurialSetupWizard + wizard = MercurialSetupWizard(self._context.state_dir) + result = wizard.run(map(os.path.expanduser, config_paths)) # Touch a file so we can periodically prompt to update extensions. state_path = os.path.join(self._context.state_dir, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/GeckoTaskTracer.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/GeckoTaskTracer.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/GeckoTaskTracer.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/GeckoTaskTracer.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -37,6 +37,7 @@ static bool sIsLoggingStarted = false; static TimeStamp sStartTime; +static const char sJSLabelPrefix[] = "#tt#"; namespace { @@ -98,8 +99,25 @@ info->mCurTraceSourceType = aType; info->mCurTaskId = newId; + int* namePtr; +#define SOURCE_EVENT_NAME(type) \ + case SourceEventType::type: \ + { \ + static int CreateSourceEvent##type; \ + namePtr = &CreateSourceEvent##type; \ + break; \ + } + + switch (aType) { +#include "SourceEventTypeMap.h" + default: + MOZ_CRASH(false); + }; +#undef CREATE_SOURCE_EVENT_NAME + // Log a fake dispatch and start for this source event. - LogDispatch(newId, newId,newId, aType); + LogDispatch(newId, newId, newId, aType); + LogVirtualTablePtr(newId, newId, namePtr); LogBegin(newId, newId); } @@ -402,5 +420,11 @@ return result; } +const char* +GetJSLabelPrefix() +{ + return sJSLabelPrefix; +} + } // namespace tasktracer } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/GeckoTaskTracer.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/GeckoTaskTracer.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/GeckoTaskTracer.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/GeckoTaskTracer.h 2014-11-26 21:46:06.000000000 +0000 @@ -44,13 +44,13 @@ class FakeTracedTask; enum SourceEventType { - UNKNOWN = 0, - TOUCH, - MOUSE, - KEY, - BLUETOOTH, - UNIXSOCKET, - WIFI + Unknown = 0, + Touch, + Mouse, + Key, + Bluetooth, + Unixsocket, + Wifi }; class AutoSourceEvent @@ -83,6 +83,8 @@ // where nsThread and base::thread release themselves. void FreeTraceInfo(); +const char* GetJSLabelPrefix(); + } // namespace tasktracer } // namespace mozilla. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/GeckoTaskTracerImpl.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/GeckoTaskTracerImpl.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/GeckoTaskTracerImpl.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/GeckoTaskTracerImpl.h 2014-11-26 21:46:06.000000000 +0000 @@ -23,8 +23,8 @@ , mCurTaskId(0) , mSavedCurTraceSourceId(0) , mSavedCurTaskId(0) - , mCurTraceSourceType(UNKNOWN) - , mSavedCurTraceSourceType(UNKNOWN) + , mCurTraceSourceType(Unknown) + , mSavedCurTraceSourceType(Unknown) , mThreadId(aThreadId) , mLastUniqueTaskId(0) , mStartLogging(aStartLogging) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/moz.build 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/moz.build 2014-11-26 21:46:06.000000000 +0000 @@ -28,6 +28,7 @@ 'JSStreamWriter.cpp', 'nsProfiler.cpp', 'nsProfilerFactory.cpp', + 'nsProfilerStartParams.cpp', 'platform.cpp', 'ProfileEntry.cpp', 'ProfilerBacktrace.cpp', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/nsIProfiler.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/nsIProfiler.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/nsIProfiler.idl 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/nsIProfiler.idl 2014-11-26 21:46:06.000000000 +0000 @@ -5,6 +5,13 @@ #include "nsISupports.idl" +%{C++ +template class nsTArray; +class nsCString; +%} + +[ref] native StringArrayRef(const nsTArray); + [scriptable, uuid(f7f3709c-04a9-45c6-8e34-40f762654a78)] interface nsIProfiler : nsISupports { @@ -37,3 +44,17 @@ AString getSharedLibraryInformation(); }; +/** + * Start-up parameters for subprocesses are passed through nsIObserverService, + * which, unfortunately, means we need to implement nsISupports in order to + * go through it. + */ +[uuid(0a175ba7-8fcf-4ce9-9c4b-ccc6272f4425)] +interface nsIProfilerStartParams : nsISupports +{ + attribute uint32_t entries; + attribute double interval; + + [noscript, notxpcom, nostdcall] StringArrayRef getFeatures(); + [noscript, notxpcom, nostdcall] StringArrayRef getThreadFilterNames(); +}; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/nsProfilerStartParams.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/nsProfilerStartParams.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/nsProfilerStartParams.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/nsProfilerStartParams.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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/. */ + +#include "nsProfilerStartParams.h" + +NS_IMPL_ISUPPORTS(nsProfilerStartParams, nsIProfilerStartParams) + +nsProfilerStartParams::nsProfilerStartParams(uint32_t aEntries, + double aInterval, + const nsTArray& aFeatures, + const nsTArray& aThreadFilterNames) : + mEntries(aEntries), + mInterval(aInterval), + mFeatures(aFeatures), + mThreadFilterNames(aThreadFilterNames) +{ +} + +nsProfilerStartParams::~nsProfilerStartParams() +{ +} + +NS_IMETHODIMP +nsProfilerStartParams::GetEntries(uint32_t* aEntries) +{ + NS_ENSURE_ARG_POINTER(aEntries); + *aEntries = mEntries; + return NS_OK; +} + +NS_IMETHODIMP +nsProfilerStartParams::SetEntries(uint32_t aEntries) +{ + NS_ENSURE_ARG(aEntries); + mEntries = aEntries; + return NS_OK; +} + +NS_IMETHODIMP +nsProfilerStartParams::GetInterval(double* aInterval) +{ + NS_ENSURE_ARG_POINTER(aInterval); + *aInterval = mInterval; + return NS_OK; +} + +NS_IMETHODIMP +nsProfilerStartParams::SetInterval(double aInterval) +{ + NS_ENSURE_ARG(aInterval); + mInterval = aInterval; + return NS_OK; +} + +const nsTArray& +nsProfilerStartParams::GetFeatures() +{ + return mFeatures; +} + +const nsTArray& +nsProfilerStartParams::GetThreadFilterNames() +{ + return mThreadFilterNames; +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/nsProfilerStartParams.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/nsProfilerStartParams.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/nsProfilerStartParams.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/nsProfilerStartParams.h 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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/. */ + +#ifndef _NSPROFILERSTARTPARAMS_H_ +#define _NSPROFILERSTARTPARAMS_H_ + +#include "nsIProfiler.h" +#include "nsString.h" +#include "nsTArray.h" + +class nsProfilerStartParams : public nsIProfilerStartParams +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPROFILERSTARTPARAMS + + nsProfilerStartParams(uint32_t aEntries, + double aInterval, + const nsTArray& aFeatures, + const nsTArray& aThreadFilterNames); + +private: + virtual ~nsProfilerStartParams(); + uint32_t mEntries; + double mInterval; + nsTArray mFeatures; + nsTArray mThreadFilterNames; +}; + +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/platform.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/platform.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/platform.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/platform.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -19,6 +19,7 @@ #include "nsIObserverService.h" #include "nsDirectoryServiceUtils.h" #include "nsDirectoryServiceDefs.h" +#include "nsProfilerStartParams.h" #include "mozilla/Services.h" #include "nsThreadUtils.h" #include "ProfilerMarkers.h" @@ -238,11 +239,6 @@ bool req2 = PR_GetEnv("MOZ_PROFILER_NEW") != nullptr; // Has v2 been requested? - bool elfhackd = false; -# if defined(USE_ELF_HACK) - bool elfhackd = true; -# endif - if (req2 && allow2) { version = 2; LOG("------------------- MOZ_PROFILER_NEW set -------------------"); @@ -250,10 +246,6 @@ version = 1; LOG("--------------- MOZ_PROFILER_NEW requested, ----------------"); LOG("---------- but is not available on this platform -----------"); - } else if (req2 && elfhackd) { - version = 1; - LOG("--------------- MOZ_PROFILER_NEW requested, ----------------"); - LOG("--- but this build was not done with --disable-elf-hack ----"); } else { version = 1; LOG("----------------- MOZ_PROFILER_NEW not set -----------------"); @@ -789,8 +781,24 @@ if (Sampler::CanNotifyObservers()) { nsCOMPtr os = mozilla::services::GetObserverService(); - if (os) - os->NotifyObservers(nullptr, "profiler-started", nullptr); + if (os) { + nsTArray featuresArray; + nsTArray threadNameFiltersArray; + + for (size_t i = 0; i < aFeatureCount; ++i) { + featuresArray.AppendElement(aFeatures[i]); + } + + for (size_t i = 0; i < aFilterCount; ++i) { + threadNameFiltersArray.AppendElement(aThreadNameFilters[i]); + } + + nsCOMPtr params = + new nsProfilerStartParams(aProfileEntries, aInterval, featuresArray, + threadNameFiltersArray); + + os->NotifyObservers(params, "profiler-started", nullptr); + } } LOG("END mozilla_sampler_start"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/platform.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/platform.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/platform.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/platform.h 2014-11-26 21:46:06.000000000 +0000 @@ -420,6 +420,9 @@ void SetPendingDelete(); bool IsPendingDelete() const { return mPendingDelete; } +#ifdef MOZ_NUWA_PROCESS + void SetThreadId(int aThreadId) { mThreadId = aThreadId; } +#endif /** * May be null for the main thread if the profiler was started during startup diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/platform-linux.cc thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/platform-linux.cc --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/platform-linux.cc 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/platform-linux.cc 2014-11-26 21:46:06.000000000 +0000 @@ -252,15 +252,9 @@ } } -// If the Nuwa process is enabled, we need to use the wrapper of tgkill() to -// perform the mapping of thread ID. -#ifdef MOZ_NUWA_PROCESS -extern "C" MFBT_API int tgkill(pid_t tgid, pid_t tid, int signalno); -#else int tgkill(pid_t tgid, pid_t tid, int signalno) { return syscall(SYS_tgkill, tgid, tid, signalno); } -#endif class PlatformData : public Malloced { public: @@ -447,6 +441,18 @@ } } +#ifdef MOZ_NUWA_PROCESS +static void +UpdateThreadId(void* aThreadInfo) { + ThreadInfo* info = static_cast(aThreadInfo); + // Note that this function is called during thread recreation. Only the thread + // calling this method is running. We can't try to acquire + // Sampler::sRegisteredThreadsMutex because it could be held by another + // thread. + info->SetThreadId(gettid()); +} +#endif + bool Sampler::RegisterCurrentThread(const char* aName, PseudoStack* aPseudoStack, bool aIsMainThread, void* stackTop) @@ -478,6 +484,20 @@ sRegisteredThreads->push_back(info); +#ifdef MOZ_NUWA_PROCESS + if (IsNuwaProcess()) { + if (info->IsMainThread()) { + // Main thread isn't a marked thread. Register UpdateThreadId() to + // NuwaAddConstructor(), which runs before all other threads are + // recreated. + NuwaAddConstructor(UpdateThreadId, info); + } else { + // Register UpdateThreadInfo() to be run when the thread is recreated. + NuwaAddThreadConstructor(UpdateThreadId, info); + } + } +#endif + uwt__register_thread_for_profiling(stackTop); return true; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/ProfileEntry.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/ProfileEntry.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/ProfileEntry.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/ProfileEntry.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -323,6 +323,10 @@ if (XRE_GetProcessType() == GeckoProcessType_Plugin) { // TODO Add the proper plugin name b.NameValue("name", "Plugin"); + } else if (XRE_GetProcessType() == GeckoProcessType_Content) { + // This isn't going to really help once we have multiple content + // processes, but it'll do for now. + b.NameValue("name", "Content"); } else { b.NameValue("name", Name()); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/SourceEventTypeMap.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/SourceEventTypeMap.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/SourceEventTypeMap.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/SourceEventTypeMap.h 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +SOURCE_EVENT_NAME(Unknown) +SOURCE_EVENT_NAME(Touch) +SOURCE_EVENT_NAME(Mouse) +SOURCE_EVENT_NAME(Key) +SOURCE_EVENT_NAME(Bluetooth) +SOURCE_EVENT_NAME(Unixsocket) +SOURCE_EVENT_NAME(Wifi) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/TracedTaskCommon.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/TracedTaskCommon.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/profiler/TracedTaskCommon.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/profiler/TracedTaskCommon.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -12,7 +12,7 @@ TracedTaskCommon::TracedTaskCommon() : mSourceEventId(0) - , mSourceEventType(SourceEventType::UNKNOWN) + , mSourceEventType(SourceEventType::Unknown) { Init(); } @@ -52,7 +52,7 @@ } info->mCurTraceSourceId = 0; - info->mCurTraceSourceType = SourceEventType::UNKNOWN; + info->mCurTraceSourceType = SourceEventType::Unknown; info->mCurTaskId = 0; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/rb/bloatdiff.pl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/rb/bloatdiff.pl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/rb/bloatdiff.pl 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/rb/bloatdiff.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,372 +0,0 @@ -#!/usr/bin/perl -w -# 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/. - - -################################################################################ - -sub usage() { - print < a.out -# **make change** -# firefox-bin -P default resource:///res/bloatcycle.html > b.out -# bloatdiff.pl a.out b.out - -EOUSAGE -} - -$OLDFILE = $ARGV[0]; -$NEWFILE = $ARGV[1]; -#$LABEL = $ARGV[2]; - -if (!$OLDFILE or - ! -e $OLDFILE or - -z $OLDFILE) { - print "\nError: Previous log file not specified, does not exist, or is empty.\n\n"; - &usage(); - exit 1; -} - -if (!$NEWFILE or - ! -e $NEWFILE or - -z $NEWFILE) { - print "\nError: Current log file not specified, does not exist, or is empty.\n\n"; - &usage(); - exit 1; -} - -sub processFile { - my ($filename, $map, $prevMap) = @_; - open(FH, $filename); - while () { - if (m{ - ^\s*(\d+)\s # Line number - ([\w:]+)\s+ # Name - (-?\d+)\s+ # Size - (-?\d+)\s+ # Leaked - (-?\d+)\s+ # Objects Total - (-?\d+)\s+ # Objects Rem - \(\s*(-?[\d.]+)\s+ # Objects Mean - \+/-\s+ - ([\w.]+)\)\s+ # Objects StdDev - (-?\d+)\s+ # Reference Total - (-?\d+)\s+ # Reference Rem - \(\s*(-?[\d.]+)\s+ # Reference Mean - \+/-\s+ - ([\w\.]+)\) # Reference StdDev - }x) { - $$map{$2} = { name => $2, - size => $3, - leaked => $4, - objTotal => $5, - objRem => $6, - objMean => $7, - objStdDev => $8, - refTotal => $9, - refRem => $10, - refMean => $11, - refStdDev => $12, - bloat => $3 * $5 # size * objTotal - }; - } else { -# print "failed to parse: $_\n"; - } - } - close(FH); -} - -%oldMap = (); -processFile($OLDFILE, \%oldMap); - -%newMap = (); -processFile($NEWFILE, \%newMap); - -################################################################################ - -$inf = 9999999.99; - -sub getLeaksDelta { - my ($key) = @_; - my $oldLeaks = $oldMap{$key}{leaked} || 0; - my $newLeaks = $newMap{$key}{leaked}; - my $percentLeaks = 0; - if ($oldLeaks == 0) { - if ($newLeaks != 0) { - # there weren't any leaks before, but now there are! - $percentLeaks = $inf; - } - } - else { - $percentLeaks = ($newLeaks - $oldLeaks) / $oldLeaks * 100; - } - # else we had no record of this class before - return ($newLeaks - $oldLeaks, $percentLeaks); -} - -################################################################################ - -sub getBloatDelta { - my ($key) = @_; - my $newBloat = $newMap{$key}{bloat}; - my $percentBloat = 0; - my $oldSize = $oldMap{$key}{size} || 0; - my $oldTotal = $oldMap{$key}{objTotal} || 0; - my $oldBloat = $oldTotal * $oldSize; - if ($oldBloat == 0) { - if ($newBloat != 0) { - # this class wasn't used before, but now it is - $percentBloat = $inf; - } - } - else { - $percentBloat = ($newBloat - $oldBloat) / $oldBloat * 100; - } - # else we had no record of this class before - return ($newBloat - $oldBloat, $percentBloat); -} - -################################################################################ - -foreach $key (keys %newMap) { - my ($newLeaks, $percentLeaks) = getLeaksDelta($key); - my ($newBloat, $percentBloat) = getBloatDelta($key); - $newMap{$key}{leakDelta} = $newLeaks; - $newMap{$key}{leakPercent} = $percentLeaks; - $newMap{$key}{bloatDelta} = $newBloat; - $newMap{$key}{bloatPercent} = $percentBloat; -} - -################################################################################ - -# Print a value of bytes out in a reasonable -# KB, MB, or GB form. Copied from build-seamonkey-util.pl, sorry. -mcafee -sub PrintSize($) { - - # print a number with 3 significant figures - sub PrintNum($) { - my ($num) = @_; - my $rv; - if ($num < 1) { - $rv = sprintf "%.3f", ($num); - } elsif ($num < 10) { - $rv = sprintf "%.2f", ($num); - } elsif ($num < 100) { - $rv = sprintf "%.1f", ($num); - } else { - $rv = sprintf "%d", ($num); - } - } - - my ($size) = @_; - my $rv; - if ($size > 1000000000) { - $rv = PrintNum($size / 1000000000.0) . "G"; - } elsif ($size > 1000000) { - $rv = PrintNum($size / 1000000.0) . "M"; - } elsif ($size > 1000) { - $rv = PrintNum($size / 1000.0) . "K"; - } else { - $rv = PrintNum($size); - } -} - - -print "Bloat/Leak Delta Report\n"; -print "--------------------------------------------------------------------------------------\n"; -print "Current file: $NEWFILE\n"; -print "Previous file: $OLDFILE\n"; -print "----------------------------------------------leaks------leaks%------bloat------bloat%\n"; - - if (! $newMap{"TOTAL"} or - ! $newMap{"TOTAL"}{bloat}) { - # It's OK if leaked or leakPercent are 0 (in fact, that would be good). - # If bloatPercent is zero, it is also OK, because we may have just had - # two runs exactly the same or with no new bloat. - print "\nError: unable to calculate bloat/leak data.\n"; - print "There is no data present.\n\n"; - print "HINT - Did your test run complete successfully?\n"; - print "HINT - Are you pointing at the right log files?\n\n"; - &usage(); - exit 1; - } - -printf "%-40s %10s %10.2f%% %10s %10.2f%%\n", - ("TOTAL", - $newMap{"TOTAL"}{leaked}, $newMap{"TOTAL"}{leakPercent}, - $newMap{"TOTAL"}{bloat}, $newMap{"TOTAL"}{bloatPercent}); - -################################################################################ - -sub percentStr { - my ($p) = @_; - if ($p == $inf) { - return "-"; - } - else { - return sprintf "%10.2f%%", $p; - } -} - -# NEW LEAKS -@keys = sort { $newMap{$b}{leakPercent} <=> $newMap{$a}{leakPercent} } keys %newMap; -my $needsHeading = 1; -my $total = 0; -foreach $key (@keys) { - my $percentLeaks = $newMap{$key}{leakPercent}; - my $leaks = $newMap{$key}{leaked}; - if ($percentLeaks > 0 && $key !~ /TOTAL/) { - if ($needsHeading) { - printf "--NEW-LEAKS-----------------------------------leaks------leaks%%-----------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks)); - $total += $leaks; - } -} -if (!$needsHeading) { - printf "%-40s %10s\n", ("TOTAL", $total); -} - -# FIXED LEAKS -@keys = sort { $newMap{$b}{leakPercent} <=> $newMap{$a}{leakPercent} } keys %newMap; -$needsHeading = 1; -$total = 0; -foreach $key (@keys) { - my $percentLeaks = $newMap{$key}{leakPercent}; - my $leaks = $newMap{$key}{leaked}; - if ($percentLeaks < 0 && $key !~ /TOTAL/) { - if ($needsHeading) { - printf "--FIXED-LEAKS---------------------------------leaks------leaks%%-----------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks)); - $total += $leaks; - } -} -if (!$needsHeading) { - printf "%-40s %10s\n", ("TOTAL", $total); -} - -# NEW BLOAT -@keys = sort { $newMap{$b}{bloatPercent} <=> $newMap{$a}{bloatPercent} } keys %newMap; -$needsHeading = 1; -$total = 0; -foreach $key (@keys) { - my $percentBloat = $newMap{$key}{bloatPercent}; - my $bloat = $newMap{$key}{bloat}; - if ($percentBloat > 0 && $key !~ /TOTAL/) { - if ($needsHeading) { - printf "--NEW-BLOAT-----------------------------------bloat------bloat%%-----------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat)); - $total += $bloat; - } -} -if (!$needsHeading) { - printf "%-40s %10s\n", ("TOTAL", $total); -} - -# ALL LEAKS -@keys = sort { $newMap{$b}{leaked} <=> $newMap{$a}{leaked} } keys %newMap; -$needsHeading = 1; -$total = 0; -foreach $key (@keys) { - my $leaks = $newMap{$key}{leaked}; - my $percentLeaks = $newMap{$key}{leakPercent}; - if ($leaks > 0) { - if ($needsHeading) { - printf "--ALL-LEAKS-----------------------------------leaks------leaks%%-----------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $leaks, percentStr($percentLeaks)); - if ($key !~ /TOTAL/) { - $total += $leaks; - } - } -} -if (!$needsHeading) { -# printf "%-40s %10s\n", ("TOTAL", $total); -} - -# ALL BLOAT -@keys = sort { $newMap{$b}{bloat} <=> $newMap{$a}{bloat} } keys %newMap; -$needsHeading = 1; -$total = 0; -foreach $key (@keys) { - my $bloat = $newMap{$key}{bloat}; - my $percentBloat = $newMap{$key}{bloatPercent}; - if ($bloat > 0) { - if ($needsHeading) { - printf "--ALL-BLOAT-----------------------------------bloat------bloat%%-----------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $bloat, percentStr($percentBloat)); - if ($key !~ /TOTAL/) { - $total += $bloat; - } - } -} -if (!$needsHeading) { -# printf "%-40s %10s\n", ("TOTAL", $total); -} - -# NEW CLASSES -@keys = sort { $newMap{$b}{bloatDelta} <=> $newMap{$a}{bloatDelta} } keys %newMap; -$needsHeading = 1; -my $ltotal = 0; -my $btotal = 0; -foreach $key (@keys) { - my $leaks = $newMap{$key}{leaked}; - my $bloat = $newMap{$key}{bloat}; - my $percentBloat = $newMap{$key}{bloatPercent}; - if ($percentBloat == $inf && $key !~ /TOTAL/) { - if ($needsHeading) { - printf "--CLASSES-NOT-REPORTED-LAST-TIME--------------leaks------bloat------------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $leaks, $bloat); - if ($key !~ /TOTAL/) { - $ltotal += $leaks; - $btotal += $bloat; - } - } -} -if (!$needsHeading) { - printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal); -} - -# OLD CLASSES -@keys = sort { ($oldMap{$b}{bloat} || 0) <=> ($oldMap{$a}{bloat} || 0) } keys %oldMap; -$needsHeading = 1; -$ltotal = 0; -$btotal = 0; -foreach $key (@keys) { - if (!defined($newMap{$key})) { - my $leaks = $oldMap{$key}{leaked}; - my $bloat = $oldMap{$key}{bloat}; - if ($needsHeading) { - printf "--CLASSES-THAT-WENT-AWAY----------------------leaks------bloat------------------------\n"; - $needsHeading = 0; - } - printf "%-40s %10s %10s\n", ($key, $leaks, $bloat); - if ($key !~ /TOTAL/) { - $ltotal += $leaks; - $btotal += $bloat; - } - } -} -if (!$needsHeading) { - printf "%-40s %10s %10s\n", ("TOTAL", $ltotal, $btotal); -} - -print "--------------------------------------------------------------------------------------\n"; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/rb/README thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/rb/README --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/tools/rb/README 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/tools/rb/README 2014-11-26 21:46:06.000000000 +0000 @@ -1,5 +1,6 @@ This is the Refcount Balancer. See -http://www.mozilla.org/performance/refcnt-balancer.html for documentation. +https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Refcount_tracing_and_balancing +for documentation. Previous CVS history for the perl scripts is available at: http://www.mozilla.org/webtools/bonsai/cvslog.cgi?file=mozilla-org/html/performance/find-leakers.pl&rev=&root=/cvsroot/ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/moz.build 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/moz.build 2014-11-26 21:46:06.000000000 +0000 @@ -84,6 +84,9 @@ 'android/nsMIMEInfoAndroid.cpp', ] elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt': + SOURCES += [ + 'unix/nsMIMEInfoQt.cpp', + ] UNIFIED_SOURCES += [ 'unix/nsGNOMERegistry.cpp', 'unix/nsMIMEInfoUnix.cpp', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#ifdef MOZ_WIDGET_QT +#include +#include +#include +#include +#endif + +#include "nsMIMEInfoQt.h" +#include "nsIURI.h" +#include "nsStringGlue.h" + +nsresult +nsMIMEInfoQt::LoadUriInternal(nsIURI * aURI) +{ +#ifdef MOZ_WIDGET_QT + nsAutoCString spec; + aURI->GetAsciiSpec(spec); + if (QDesktopServices::openUrl(QUrl(spec.get()))) { + return NS_OK; + } +#endif + + return NS_ERROR_FAILURE; +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/unix/nsMIMEInfoQt.h 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#ifndef nsMIMEInfoQt_h_ +#define nsMIMEInfoQt_h_ + +#include "nsCOMPtr.h" + +class nsIURI; + +class nsMIMEInfoQt +{ +public: + static nsresult LoadUriInternal(nsIURI * aURI); +}; + +#endif // nsMIMEInfoQt_h_ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -5,9 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef MOZ_WIDGET_QT -#include -#include -#include #if (MOZ_ENABLE_CONTENTACTION) #include #include "nsContentHandlerApp.h" @@ -24,6 +21,9 @@ #ifdef MOZ_ENABLE_DBUS #include "nsDBusHandlerApp.h" #endif +#ifdef MOZ_WIDGET_QT +#include "nsMIMEInfoQt.h" +#endif nsresult nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI) @@ -32,11 +32,7 @@ #ifdef MOZ_WIDGET_QT if (NS_FAILED(rv)) { - nsAutoCString spec; - aURI->GetAsciiSpec(spec); - if (QDesktopServices::openUrl(QUrl(spec.get()))) { - rv = NS_OK; - } + rv = nsMIMEInfoQt::LoadUriInternal(aURI); } #endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/prefetch/nsOfflineCacheUpdateService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/prefetch/nsOfflineCacheUpdateService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/prefetch/nsOfflineCacheUpdateService.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/prefetch/nsOfflineCacheUpdateService.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -45,7 +45,7 @@ #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeOwner.h" -#include "mozilla/dom/TabChild.h" +#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/PermissionMessageUtils.h" #include "nsContentUtils.h" #include "mozilla/unused.h" @@ -747,8 +747,7 @@ nsresult rv; if (GeckoProcessType_Default != XRE_GetProcessType()) { - TabChild* child = TabChild::GetFrom(aWindow); - NS_ENSURE_TRUE(child, NS_ERROR_FAILURE); + ContentChild* child = ContentChild::GetSingleton(); if (!child->SendSetOfflinePermission(IPC::Principal(aPrincipal))) { return NS_ERROR_FAILURE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/prefetch/OfflineCacheUpdateChild.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/prefetch/OfflineCacheUpdateChild.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/prefetch/OfflineCacheUpdateChild.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/prefetch/OfflineCacheUpdateChild.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -34,6 +34,7 @@ using namespace mozilla::ipc; using namespace mozilla::net; using mozilla::dom::TabChild; +using mozilla::dom::ContentChild; #if defined(PR_LOGGING) // @@ -433,10 +434,11 @@ // Need to addref ourself here, because the IPC stack doesn't hold // a reference to us. Will be released in RecvFinish() that identifies // the work has been done. - child->SendPOfflineCacheUpdateConstructor(this, manifestURI, documentURI, - stickDocument); + ContentChild::GetSingleton()->SendPOfflineCacheUpdateConstructor( + this, manifestURI, documentURI, + stickDocument, child->GetTabId()); - // TabChild::DeallocPOfflineCacheUpdate will release this. + // ContentChild::DeallocPOfflineCacheUpdate will release this. NS_ADDREF_THIS(); return NS_OK; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/prefetch/POfflineCacheUpdate.ipdl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/prefetch/POfflineCacheUpdate.ipdl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/uriloader/prefetch/POfflineCacheUpdate.ipdl 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/uriloader/prefetch/POfflineCacheUpdate.ipdl 2014-11-26 21:46:06.000000000 +0000 @@ -5,7 +5,7 @@ * 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/. */ -include protocol PBrowser; +include protocol PContent; namespace mozilla { namespace docshell { @@ -13,7 +13,7 @@ //------------------------------------------------------------------- protocol POfflineCacheUpdate { - manager PBrowser; + manager PContent; parent: __delete__(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/view/nsView.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/view/nsView.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/view/nsView.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/view/nsView.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -337,14 +337,14 @@ // only two scales are 1.0 or 2.0, and so the quantization doesn't actually // cause problems anyhow). // In the case of a mismatch, fall back to scaling based on the dev context's - // unscaledAppUnitsPerDevPixel value. On platforms where the device-pixel + // AppUnitsPerDevPixelAtUnitFullZoom value. On platforms where the device-pixel // scale is uniform across all displays (currently all except OS X), we'll // always use the precise value from mWindow->GetDefaultScale here. CSSToLayoutDeviceScale scale = widget->GetDefaultScale(); - if (NSToIntRound(60.0 / scale.scale) == dx->UnscaledAppUnitsPerDevPixel()) { + if (NSToIntRound(60.0 / scale.scale) == dx->AppUnitsPerDevPixelAtUnitFullZoom()) { invScale = 1.0 / scale.scale; } else { - invScale = dx->UnscaledAppUnitsPerDevPixel() / 60.0; + invScale = dx->AppUnitsPerDevPixelAtUnitFullZoom() / 60.0; } if (changedPos) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/content/mochitest.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/content/mochitest.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/content/mochitest.js 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/content/mochitest.js 2014-11-26 21:46:06.000000000 +0000 @@ -20,7 +20,7 @@ Cu.import("resource://gre/modules/Webapps.jsm"); -becomeWebapp("http://mochi.test:8888/tests/webapprt/test/content/test.webapp", +becomeWebapp("http://mochi.test:8888/webapprtContent/webapprt/test/content/test.webapp", undefined, function onBecome() { if (window.arguments && window.arguments[0]) { let testUrl = window.arguments[0].QueryInterface(Ci.nsIPropertyBag2).get("url"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/locales/en-US/webapprt/overrides/appstrings.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/locales/en-US/webapprt/overrides/appstrings.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/locales/en-US/webapprt/overrides/appstrings.properties 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/locales/en-US/webapprt/overrides/appstrings.properties 2014-11-26 21:46:06.000000000 +0000 @@ -30,6 +30,6 @@ externalProtocolLaunchBtn=Launch application malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences. phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information. -cspFrameAncestorBlocked=This application tried to access a resource that has a content security policy that prevents it from being embedded in this way. +cspBlocked=This application tried to access a resource that has a content security policy that prevents it from being loaded in this way. corruptedContentError=The application cannot continue loading because an error in the data transmission was detected. remoteXUL=This application tried to use an unsupported technology that is no longer available. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/moz.build 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/moz.build 2014-11-26 21:46:06.000000000 +0000 @@ -37,7 +37,7 @@ 'test/chrome/downloads/webapprt.ini', 'test/chrome/webapprt.ini', ] -MOCHITEST_MANIFESTS += ['test/content/mochitest.ini'] +MOCHITEST_WEBAPPRT_CONTENT_MANIFESTS += ['test/content/webapprt.ini'] # Place webapprt resources in a separate app dir DIST_SUBDIR = 'webapprt' diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/test/content/mochitest.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/test/content/mochitest.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/test/content/mochitest.ini 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/test/content/mochitest.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -[DEFAULT] -skip-if = buildapp == 'b2g' -support-files = - test.webapp - test.webapp^headers^ - -[webapprt_sample.html] -[webapprt_indexeddb.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/test/content/webapprt.ini thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/test/content/webapprt.ini --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/webapprt/test/content/webapprt.ini 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/webapprt/test/content/webapprt.ini 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,8 @@ +[DEFAULT] +skip-if = buildapp == 'b2g' +support-files = + test.webapp + test.webapp^headers^ + +[webapprt_sample.html] +[webapprt_indexeddb.html] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/AndroidBridge.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/AndroidBridge.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/AndroidBridge.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/AndroidBridge.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -41,7 +41,9 @@ #include "nsContentUtils.h" #include "nsIScriptError.h" #include "nsIHttpChannel.h" -#include "GeneratedSDKWrappers.h" + +#include "MediaCodec.h" +#include "SurfaceTexture.h" using namespace mozilla; using namespace mozilla::widget::android; @@ -222,8 +224,11 @@ InitAndroidJavaWrappers(jEnv); if (mAPIVersion >= 16 /* Jelly Bean */) { - // We only use this for MediaCodec right now - InitSDKStubs(jEnv); + sdk::InitMediaCodecStubs(jEnv); + } + + if (mAPIVersion >= 14 /* ICS */) { + sdk::InitSurfaceTextureStubs(jEnv); } // jEnv should NOT be cached here by anything -- the jEnv here diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/AndroidJavaWrappers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/AndroidJavaWrappers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/AndroidJavaWrappers.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/AndroidJavaWrappers.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -11,7 +11,6 @@ #include "mozilla/BasicEvents.h" #include "mozilla/TimeStamp.h" #include "mozilla/TouchEvents.h" -#include "GeneratedSDKWrappers.h" using namespace mozilla; using namespace mozilla::dom; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/Makefile.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/Makefile.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/Makefile.in 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,28 @@ +# 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/. + +annotation_processor_jar_files := $(DEPTH)/build/annotationProcessors/annotationProcessors.jar:$(ANDROID_TOOLS)/lib/lint.jar:$(ANDROID_TOOLS)/lib/lint-checks.jar + +sdk_processor := \ + $(JAVA) \ + -Dcom.android.tools.lint.bindir='$(ANDROID_TOOLS)' \ + -classpath $(annotation_processor_jar_files) \ + org.mozilla.gecko.annotationProcessors.SDKProcessor + +# For the benefit of readers: the following pattern rule says that, +# for example, MediaCodec.cpp and MediaCodec.h can be produced from +# MediaCodec-classes.txt. This formulation invokes the SDK processor +# at most once. + +%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt + $(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16 + +# We'd like these to be defined in a future GENERATED_EXPORTS list. +bindings_exports_FILES := \ + MediaCodec.h \ + SurfaceTexture.h \ + $(NULL) +bindings_exports_DEST = $(DIST)/include +bindings_exports_TARGET := export +INSTALL_TARGETS += bindings_exports diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/MediaCodec-classes.txt thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/MediaCodec-classes.txt --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/MediaCodec-classes.txt 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/MediaCodec-classes.txt 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,3 @@ +android.media.MediaCodec +android.media.MediaCodec$BufferInfo +android.media.MediaFormat diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/moz.build 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/moz.build 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,35 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +# List of stems to generate .cpp and .h files for. To add a stem, add it to +# this list and ensure that $(stem)-classes.txt exists in this directory. +generated = [ + 'MediaCodec', + 'SurfaceTexture', +] + +GENERATED_SOURCES += [stem + '.cpp' for stem in generated] + +# We'd like to add these to a future GENERATED_EXPORTS list, but for now we mark +# them as generated here and manually install them in Makefile.in. +GENERATED_FILES += [stem + '.h' for stem in generated] + +# There is an unfortunate race condition when using GENERATED_SOURCES and +# pattern rules (see Makefile.in) that manifests itself as a VPATH resolution +# conflict: MediaCodec.o looks for MediaCodec.cpp and $(CURDIR)/MediaCodec.cpp, +# and the pattern rule is matched but doesn't resolve both sources, causing a +# failure. Adding the GENERATED_SOURCES to GENERATED_FILES causes the sources +# to be built at export time, which is before MediaCodec.o needs them; and by +# the time MediaCodec.o is built, the source is in place and the VPATH +# resolution works as expected. +GENERATED_FILES += GENERATED_SOURCES + +FAIL_ON_WARNINGS = True +FINAL_LIBRARY = 'xul' + +LOCAL_INCLUDES += [ + '/widget/android', +] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/SurfaceTexture-classes.txt thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/SurfaceTexture-classes.txt --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/bindings/SurfaceTexture-classes.txt 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/bindings/SurfaceTexture-classes.txt 2014-11-26 21:46:06.000000000 +0000 @@ -0,0 +1,2 @@ +android.graphics.SurfaceTexture +android.view.Surface diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedJNIWrappers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedJNIWrappers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedJNIWrappers.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedJNIWrappers.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -13,11 +13,9 @@ namespace android { jclass DownloadsIntegration::mDownloadsIntegrationClass = 0; jmethodID DownloadsIntegration::jScanMedia = 0; -void DownloadsIntegration::InitStubs(JNIEnv *jEnv) { - initInit(); - - mDownloadsIntegrationClass = getClassGlobalRef("org/mozilla/gecko/DownloadsIntegration"); - jScanMedia = getStaticMethod("scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V"); +void DownloadsIntegration::InitStubs(JNIEnv *env) { + mDownloadsIntegrationClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/DownloadsIntegration"); + jScanMedia = AndroidBridge::GetStaticMethodID(env, mDownloadsIntegrationClass, "scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V"); } DownloadsIntegration* DownloadsIntegration::Wrap(jobject obj) { @@ -124,92 +122,90 @@ jmethodID GeckoAppShell::jUnregisterSurfaceTextureFrameListener = 0; jmethodID GeckoAppShell::jVibrate1 = 0; jmethodID GeckoAppShell::jVibrateA = 0; -void GeckoAppShell::InitStubs(JNIEnv *jEnv) { - initInit(); - - mGeckoAppShellClass = getClassGlobalRef("org/mozilla/gecko/GeckoAppShell"); - jAcknowledgeEvent = getStaticMethod("acknowledgeEvent", "()V"); - jAddPluginViewWrapper = getStaticMethod("addPluginView", "(Landroid/view/View;FFFFZ)V"); - jAlertsProgressListener_OnProgress = getStaticMethod("alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)V"); - jCancelVibrate = getStaticMethod("cancelVibrate", "()V"); - jCheckURIVisited = getStaticMethod("checkUriVisited", "(Ljava/lang/String;)V"); - jClearMessageList = getStaticMethod("clearMessageList", "(I)V"); - jCloseCamera = getStaticMethod("closeCamera", "()V"); - jCloseNotification = getStaticMethod("closeNotification", "(Ljava/lang/String;)V"); - jConnectionGetMimeType = getStaticMethod("connectionGetMimeType", "(Ljava/net/URLConnection;)Ljava/lang/String;"); - jCreateInputStream = getStaticMethod("createInputStream", "(Ljava/net/URLConnection;)Ljava/io/InputStream;"); - jCreateMessageListWrapper = getStaticMethod("createMessageList", "(JJ[Ljava/lang/String;ILjava/lang/String;ZZJZI)V"); - jCreateShortcut = getStaticMethod("createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - jDeleteMessageWrapper = getStaticMethod("deleteMessage", "(II)V"); - jDisableBatteryNotifications = getStaticMethod("disableBatteryNotifications", "()V"); - jDisableNetworkNotifications = getStaticMethod("disableNetworkNotifications", "()V"); - jDisableScreenOrientationNotifications = getStaticMethod("disableScreenOrientationNotifications", "()V"); - jDisableSensor = getStaticMethod("disableSensor", "(I)V"); - jEnableBatteryNotifications = getStaticMethod("enableBatteryNotifications", "()V"); - jEnableLocation = getStaticMethod("enableLocation", "(Z)V"); - jEnableLocationHighAccuracy = getStaticMethod("enableLocationHighAccuracy", "(Z)V"); - jEnableNetworkNotifications = getStaticMethod("enableNetworkNotifications", "()V"); - jEnableScreenOrientationNotifications = getStaticMethod("enableScreenOrientationNotifications", "()V"); - jEnableSensor = getStaticMethod("enableSensor", "(I)V"); - jGamepadAdded = getStaticMethod("gamepadAdded", "(II)V"); - jGetConnection = getStaticMethod("getConnection", "(Ljava/lang/String;)Ljava/net/URLConnection;"); - jGetContext = getStaticMethod("getContext", "()Landroid/content/Context;"); - jGetCurrentBatteryInformationWrapper = getStaticMethod("getCurrentBatteryInformation", "()[D"); - jGetCurrentNetworkInformationWrapper = getStaticMethod("getCurrentNetworkInformation", "()[D"); - jGetDensity = getStaticMethod("getDensity", "()F"); - jGetDpiWrapper = getStaticMethod("getDpi", "()I"); - jGetExtensionFromMimeTypeWrapper = getStaticMethod("getExtensionFromMimeType", "(Ljava/lang/String;)Ljava/lang/String;"); - jGetExternalPublicDirectory = getStaticMethod("getExternalPublicDirectory", "(Ljava/lang/String;)Ljava/lang/String;"); - jGetHandlersForMimeTypeWrapper = getStaticMethod("getHandlersForMimeType", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"); - jGetHandlersForURLWrapper = getStaticMethod("getHandlersForURL", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"); - jGetIconForExtensionWrapper = getStaticMethod("getIconForExtension", "(Ljava/lang/String;I)[B"); - jGetMessageWrapper = getStaticMethod("getMessage", "(II)V"); - jGetMimeTypeFromExtensionsWrapper = getStaticMethod("getMimeTypeFromExtensions", "(Ljava/lang/String;)Ljava/lang/String;"); - jGetNextMessageInListWrapper = getStaticMethod("getNextMessageInList", "(II)V"); - jGetProxyForURIWrapper = getStaticMethod("getProxyForURI", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;"); - jGetScreenDepthWrapper = getStaticMethod("getScreenDepth", "()I"); - jGetScreenOrientationWrapper = getStaticMethod("getScreenOrientation", "()S"); - jGetShowPasswordSetting = getStaticMethod("getShowPasswordSetting", "()Z"); - jGetSystemColoursWrapper = getStaticMethod("getSystemColors", "()[I"); - jHandleGeckoMessageWrapper = getStaticMethod("handleGeckoMessage", "(Lorg/mozilla/gecko/util/NativeJSContainer;)V"); - jHandleUncaughtException = getStaticMethod("handleUncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); - jHideProgressDialog = getStaticMethod("hideProgressDialog", "()V"); - jInitCameraWrapper = getStaticMethod("initCamera", "(Ljava/lang/String;III)[I"); - jIsNetworkLinkKnown = getStaticMethod("isNetworkLinkKnown", "()Z"); - jIsNetworkLinkUp = getStaticMethod("isNetworkLinkUp", "()Z"); - jIsTablet = getStaticMethod("isTablet", "()Z"); - jKillAnyZombies = getStaticMethod("killAnyZombies", "()V"); - jLoadPluginClass = getStaticMethod("loadPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"); - jLockScreenOrientation = getStaticMethod("lockScreenOrientation", "(I)V"); - jMarkURIVisited = getStaticMethod("markUriVisited", "(Ljava/lang/String;)V"); - jMoveTaskToBack = getStaticMethod("moveTaskToBack", "()V"); - jNetworkLinkType = getStaticMethod("networkLinkType", "()I"); - jNotifyDefaultPrevented = getStaticMethod("notifyDefaultPrevented", "(Z)V"); - jNotifyIME = getStaticMethod("notifyIME", "(I)V"); - jNotifyIMEChange = getStaticMethod("notifyIMEChange", "(Ljava/lang/String;III)V"); - jNotifyIMEContext = getStaticMethod("notifyIMEContext", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - jNotifyWakeLockChanged = getStaticMethod("notifyWakeLockChanged", "(Ljava/lang/String;Ljava/lang/String;)V"); - jNotifyXreExit = getStaticMethod("onXreExit", "()V"); - jOpenUriExternal = getStaticMethod("openUriExternal", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z"); - jPerformHapticFeedback = getStaticMethod("performHapticFeedback", "(Z)V"); - jPumpMessageLoop = getStaticMethod("pumpMessageLoop", "()Z"); - jRegisterSurfaceTextureFrameListener = getStaticMethod("registerSurfaceTextureFrameListener", "(Ljava/lang/Object;I)V"); - jRemovePluginView = getStaticMethod("removePluginView", "(Landroid/view/View;Z)V"); - jRequestUiThreadCallback = getStaticMethod("requestUiThreadCallback", "(J)V"); - jScheduleRestart = getStaticMethod("scheduleRestart", "()V"); - jSendMessageWrapper = getStaticMethod("sendMessage", "(Ljava/lang/String;Ljava/lang/String;I)V"); - jSetFullScreen = getStaticMethod("setFullScreen", "(Z)V"); - jSetKeepScreenOn = getStaticMethod("setKeepScreenOn", "(Z)V"); - jSetURITitle = getStaticMethod("setUriTitle", "(Ljava/lang/String;Ljava/lang/String;)V"); - jShowAlertNotificationWrapper = getStaticMethod("showAlertNotification", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - jShowInputMethodPicker = getStaticMethod("showInputMethodPicker", "()V"); - jStartMonitoringGamepad = getStaticMethod("startMonitoringGamepad", "()V"); - jStopMonitoringGamepad = getStaticMethod("stopMonitoringGamepad", "()V"); - jUnlockProfile = getStaticMethod("unlockProfile", "()Z"); - jUnlockScreenOrientation = getStaticMethod("unlockScreenOrientation", "()V"); - jUnregisterSurfaceTextureFrameListener = getStaticMethod("unregisterSurfaceTextureFrameListener", "(Ljava/lang/Object;)V"); - jVibrate1 = getStaticMethod("vibrate", "(J)V"); - jVibrateA = getStaticMethod("vibrate", "([JI)V"); +void GeckoAppShell::InitStubs(JNIEnv *env) { + mGeckoAppShellClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/GeckoAppShell"); + jAcknowledgeEvent = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "acknowledgeEvent", "()V"); + jAddPluginViewWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "addPluginView", "(Landroid/view/View;FFFFZ)V"); + jAlertsProgressListener_OnProgress = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)V"); + jCancelVibrate = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "cancelVibrate", "()V"); + jCheckURIVisited = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "checkUriVisited", "(Ljava/lang/String;)V"); + jClearMessageList = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "clearMessageList", "(I)V"); + jCloseCamera = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "closeCamera", "()V"); + jCloseNotification = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "closeNotification", "(Ljava/lang/String;)V"); + jConnectionGetMimeType = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "connectionGetMimeType", "(Ljava/net/URLConnection;)Ljava/lang/String;"); + jCreateInputStream = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "createInputStream", "(Ljava/net/URLConnection;)Ljava/io/InputStream;"); + jCreateMessageListWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "createMessageList", "(JJ[Ljava/lang/String;ILjava/lang/String;ZZJZI)V"); + jCreateShortcut = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + jDeleteMessageWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "deleteMessage", "(II)V"); + jDisableBatteryNotifications = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "disableBatteryNotifications", "()V"); + jDisableNetworkNotifications = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "disableNetworkNotifications", "()V"); + jDisableScreenOrientationNotifications = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "disableScreenOrientationNotifications", "()V"); + jDisableSensor = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "disableSensor", "(I)V"); + jEnableBatteryNotifications = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "enableBatteryNotifications", "()V"); + jEnableLocation = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "enableLocation", "(Z)V"); + jEnableLocationHighAccuracy = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "enableLocationHighAccuracy", "(Z)V"); + jEnableNetworkNotifications = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "enableNetworkNotifications", "()V"); + jEnableScreenOrientationNotifications = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "enableScreenOrientationNotifications", "()V"); + jEnableSensor = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "enableSensor", "(I)V"); + jGamepadAdded = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "gamepadAdded", "(II)V"); + jGetConnection = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getConnection", "(Ljava/lang/String;)Ljava/net/URLConnection;"); + jGetContext = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getContext", "()Landroid/content/Context;"); + jGetCurrentBatteryInformationWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getCurrentBatteryInformation", "()[D"); + jGetCurrentNetworkInformationWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getCurrentNetworkInformation", "()[D"); + jGetDensity = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getDensity", "()F"); + jGetDpiWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getDpi", "()I"); + jGetExtensionFromMimeTypeWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getExtensionFromMimeType", "(Ljava/lang/String;)Ljava/lang/String;"); + jGetExternalPublicDirectory = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getExternalPublicDirectory", "(Ljava/lang/String;)Ljava/lang/String;"); + jGetHandlersForMimeTypeWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getHandlersForMimeType", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"); + jGetHandlersForURLWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getHandlersForURL", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"); + jGetIconForExtensionWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getIconForExtension", "(Ljava/lang/String;I)[B"); + jGetMessageWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getMessage", "(II)V"); + jGetMimeTypeFromExtensionsWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getMimeTypeFromExtensions", "(Ljava/lang/String;)Ljava/lang/String;"); + jGetNextMessageInListWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getNextMessageInList", "(II)V"); + jGetProxyForURIWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getProxyForURI", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;"); + jGetScreenDepthWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getScreenDepth", "()I"); + jGetScreenOrientationWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getScreenOrientation", "()S"); + jGetShowPasswordSetting = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getShowPasswordSetting", "()Z"); + jGetSystemColoursWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "getSystemColors", "()[I"); + jHandleGeckoMessageWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "handleGeckoMessage", "(Lorg/mozilla/gecko/util/NativeJSContainer;)V"); + jHandleUncaughtException = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "handleUncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); + jHideProgressDialog = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "hideProgressDialog", "()V"); + jInitCameraWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "initCamera", "(Ljava/lang/String;III)[I"); + jIsNetworkLinkKnown = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "isNetworkLinkKnown", "()Z"); + jIsNetworkLinkUp = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "isNetworkLinkUp", "()Z"); + jIsTablet = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "isTablet", "()Z"); + jKillAnyZombies = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "killAnyZombies", "()V"); + jLoadPluginClass = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "loadPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"); + jLockScreenOrientation = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "lockScreenOrientation", "(I)V"); + jMarkURIVisited = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "markUriVisited", "(Ljava/lang/String;)V"); + jMoveTaskToBack = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "moveTaskToBack", "()V"); + jNetworkLinkType = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "networkLinkType", "()I"); + jNotifyDefaultPrevented = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "notifyDefaultPrevented", "(Z)V"); + jNotifyIME = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "notifyIME", "(I)V"); + jNotifyIMEChange = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "notifyIMEChange", "(Ljava/lang/String;III)V"); + jNotifyIMEContext = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "notifyIMEContext", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + jNotifyWakeLockChanged = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "notifyWakeLockChanged", "(Ljava/lang/String;Ljava/lang/String;)V"); + jNotifyXreExit = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "onXreExit", "()V"); + jOpenUriExternal = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "openUriExternal", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z"); + jPerformHapticFeedback = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "performHapticFeedback", "(Z)V"); + jPumpMessageLoop = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "pumpMessageLoop", "()Z"); + jRegisterSurfaceTextureFrameListener = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "registerSurfaceTextureFrameListener", "(Ljava/lang/Object;I)V"); + jRemovePluginView = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "removePluginView", "(Landroid/view/View;Z)V"); + jRequestUiThreadCallback = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "requestUiThreadCallback", "(J)V"); + jScheduleRestart = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "scheduleRestart", "()V"); + jSendMessageWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "sendMessage", "(Ljava/lang/String;Ljava/lang/String;I)V"); + jSetFullScreen = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "setFullScreen", "(Z)V"); + jSetKeepScreenOn = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "setKeepScreenOn", "(Z)V"); + jSetURITitle = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "setUriTitle", "(Ljava/lang/String;Ljava/lang/String;)V"); + jShowAlertNotificationWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "showAlertNotification", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + jShowInputMethodPicker = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "showInputMethodPicker", "()V"); + jStartMonitoringGamepad = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "startMonitoringGamepad", "()V"); + jStopMonitoringGamepad = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "stopMonitoringGamepad", "()V"); + jUnlockProfile = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "unlockProfile", "()Z"); + jUnlockScreenOrientation = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "unlockScreenOrientation", "()V"); + jUnregisterSurfaceTextureFrameListener = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "unregisterSurfaceTextureFrameListener", "(Ljava/lang/Object;)V"); + jVibrate1 = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "vibrate", "(J)V"); + jVibrateA = AndroidBridge::GetStaticMethodID(env, mGeckoAppShellClass, "vibrate", "([JI)V"); } GeckoAppShell* GeckoAppShell::Wrap(jobject obj) { @@ -1342,17 +1338,15 @@ jmethodID GeckoJavaSampler::jStartJavaProfiling = 0; jmethodID GeckoJavaSampler::jStopJavaProfiling = 0; jmethodID GeckoJavaSampler::jUnpauseJavaProfiling = 0; -void GeckoJavaSampler::InitStubs(JNIEnv *jEnv) { - initInit(); - - mGeckoJavaSamplerClass = getClassGlobalRef("org/mozilla/gecko/GeckoJavaSampler"); - jGetFrameNameJavaProfilingWrapper = getStaticMethod("getFrameName", "(III)Ljava/lang/String;"); - jGetSampleTimeJavaProfiling = getStaticMethod("getSampleTime", "(II)D"); - jGetThreadNameJavaProfilingWrapper = getStaticMethod("getThreadName", "(I)Ljava/lang/String;"); - jPauseJavaProfiling = getStaticMethod("pause", "()V"); - jStartJavaProfiling = getStaticMethod("start", "(II)V"); - jStopJavaProfiling = getStaticMethod("stop", "()V"); - jUnpauseJavaProfiling = getStaticMethod("unpause", "()V"); +void GeckoJavaSampler::InitStubs(JNIEnv *env) { + mGeckoJavaSamplerClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/GeckoJavaSampler"); + jGetFrameNameJavaProfilingWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "getFrameName", "(III)Ljava/lang/String;"); + jGetSampleTimeJavaProfiling = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "getSampleTime", "(II)D"); + jGetThreadNameJavaProfilingWrapper = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "getThreadName", "(I)Ljava/lang/String;"); + jPauseJavaProfiling = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "pause", "()V"); + jStartJavaProfiling = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "start", "(II)V"); + jStopJavaProfiling = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "stop", "()V"); + jUnpauseJavaProfiling = AndroidBridge::GetStaticMethodID(env, mGeckoJavaSamplerClass, "unpause", "()V"); } GeckoJavaSampler* GeckoJavaSampler::Wrap(jobject obj) { @@ -1457,13 +1451,11 @@ jmethodID RestrictedProfiles::jGetUserRestrictions = 0; jmethodID RestrictedProfiles::jIsAllowed = 0; jmethodID RestrictedProfiles::jIsUserRestricted = 0; -void RestrictedProfiles::InitStubs(JNIEnv *jEnv) { - initInit(); - - mRestrictedProfilesClass = getClassGlobalRef("org/mozilla/gecko/RestrictedProfiles"); - jGetUserRestrictions = getStaticMethod("getUserRestrictions", "()Ljava/lang/String;"); - jIsAllowed = getStaticMethod("isAllowed", "(ILjava/lang/String;)Z"); - jIsUserRestricted = getStaticMethod("isUserRestricted", "()Z"); +void RestrictedProfiles::InitStubs(JNIEnv *env) { + mRestrictedProfilesClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/RestrictedProfiles"); + jGetUserRestrictions = AndroidBridge::GetStaticMethodID(env, mRestrictedProfilesClass, "getUserRestrictions", "()Ljava/lang/String;"); + jIsAllowed = AndroidBridge::GetStaticMethodID(env, mRestrictedProfilesClass, "isAllowed", "(ILjava/lang/String;)Z"); + jIsUserRestricted = AndroidBridge::GetStaticMethodID(env, mRestrictedProfilesClass, "isUserRestricted", "()Z"); } RestrictedProfiles* RestrictedProfiles::Wrap(jobject obj) { @@ -1519,15 +1511,13 @@ jfieldID SurfaceBits::jformat = 0; jfieldID SurfaceBits::jheight = 0; jfieldID SurfaceBits::jwidth = 0; -void SurfaceBits::InitStubs(JNIEnv *jEnv) { - initInit(); - - mSurfaceBitsClass = getClassGlobalRef("org/mozilla/gecko/SurfaceBits"); - jSurfaceBits = getMethod("", "()V"); - jbuffer = getField("buffer", "Ljava/nio/ByteBuffer;"); - jformat = getField("format", "I"); - jheight = getField("height", "I"); - jwidth = getField("width", "I"); +void SurfaceBits::InitStubs(JNIEnv *env) { + mSurfaceBitsClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/SurfaceBits"); + jSurfaceBits = AndroidBridge::GetMethodID(env, mSurfaceBitsClass, "", "()V"); + jbuffer = AndroidBridge::GetFieldID(env, mSurfaceBitsClass, "buffer", "Ljava/nio/ByteBuffer;"); + jformat = AndroidBridge::GetFieldID(env, mSurfaceBitsClass, "format", "I"); + jheight = AndroidBridge::GetFieldID(env, mSurfaceBitsClass, "height", "I"); + jwidth = AndroidBridge::GetFieldID(env, mSurfaceBitsClass, "width", "I"); } SurfaceBits* SurfaceBits::Wrap(jobject obj) { @@ -1589,11 +1579,9 @@ } jclass ThumbnailHelper::mThumbnailHelperClass = 0; jmethodID ThumbnailHelper::jSendThumbnail = 0; -void ThumbnailHelper::InitStubs(JNIEnv *jEnv) { - initInit(); - - mThumbnailHelperClass = getClassGlobalRef("org/mozilla/gecko/ThumbnailHelper"); - jSendThumbnail = getStaticMethod("notifyThumbnail", "(Ljava/nio/ByteBuffer;IZZ)V"); +void ThumbnailHelper::InitStubs(JNIEnv *env) { + mThumbnailHelperClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/ThumbnailHelper"); + jSendThumbnail = AndroidBridge::GetStaticMethodID(env, mThumbnailHelperClass, "notifyThumbnail", "(Ljava/nio/ByteBuffer;IZZ)V"); } ThumbnailHelper* ThumbnailHelper::Wrap(jobject obj) { @@ -1624,13 +1612,11 @@ jmethodID DisplayPortMetrics::jDisplayPortMetrics = 0; jfieldID DisplayPortMetrics::jMPosition = 0; jfieldID DisplayPortMetrics::jResolution = 0; -void DisplayPortMetrics::InitStubs(JNIEnv *jEnv) { - initInit(); - - mDisplayPortMetricsClass = getClassGlobalRef("org/mozilla/gecko/gfx/DisplayPortMetrics"); - jDisplayPortMetrics = getMethod("", "(FFFFF)V"); - jMPosition = getField("mPosition", "Landroid/graphics/RectF;"); - jResolution = getField("resolution", "F"); +void DisplayPortMetrics::InitStubs(JNIEnv *env) { + mDisplayPortMetricsClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/DisplayPortMetrics"); + jDisplayPortMetrics = AndroidBridge::GetMethodID(env, mDisplayPortMetricsClass, "", "(FFFFF)V"); + jMPosition = AndroidBridge::GetFieldID(env, mDisplayPortMetricsClass, "mPosition", "Landroid/graphics/RectF;"); + jResolution = AndroidBridge::GetFieldID(env, mDisplayPortMetricsClass, "resolution", "F"); } DisplayPortMetrics* DisplayPortMetrics::Wrap(jobject obj) { @@ -1669,11 +1655,9 @@ } jclass GLController::mGLControllerClass = 0; jmethodID GLController::jCreateEGLSurfaceForCompositorWrapper = 0; -void GLController::InitStubs(JNIEnv *jEnv) { - initInit(); - - mGLControllerClass = getClassGlobalRef("org/mozilla/gecko/gfx/GLController"); - jCreateEGLSurfaceForCompositorWrapper = getMethod("createEGLSurfaceForCompositor", "()Ljavax/microedition/khronos/egl/EGLSurface;"); +void GLController::InitStubs(JNIEnv *env) { + mGLControllerClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/GLController"); + jCreateEGLSurfaceForCompositorWrapper = AndroidBridge::GetMethodID(env, mGLControllerClass, "createEGLSurfaceForCompositor", "()Ljavax/microedition/khronos/egl/EGLSurface;"); } GLController* GLController::Wrap(jobject obj) { @@ -1707,21 +1691,19 @@ jmethodID GeckoLayerClient::jSetPageRect = 0; jmethodID GeckoLayerClient::jSyncFrameMetrics = 0; jmethodID GeckoLayerClient::jSyncViewportInfo = 0; -void GeckoLayerClient::InitStubs(JNIEnv *jEnv) { - initInit(); - - mGeckoLayerClientClass = getClassGlobalRef("org/mozilla/gecko/gfx/GeckoLayerClient"); - jActivateProgram = getMethod("activateProgram", "()V"); - jContentDocumentChanged = getMethod("contentDocumentChanged", "()V"); - jCreateFrame = getMethod("createFrame", "()Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;"); - jDeactivateProgramAndRestoreState = getMethod("deactivateProgramAndRestoreState", "(ZIIII)V"); - jGetDisplayPort = getMethod("getDisplayPort", "(ZZILorg/mozilla/gecko/gfx/ImmutableViewportMetrics;)Lorg/mozilla/gecko/gfx/DisplayPortMetrics;"); - jIsContentDocumentDisplayed = getMethod("isContentDocumentDisplayed", "()Z"); - jProgressiveUpdateCallback = getMethod("progressiveUpdateCallback", "(ZFFFFFZ)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;"); - jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFF)V"); - jSetPageRect = getMethod("setPageRect", "(FFFF)V"); - jSyncFrameMetrics = getMethod("syncFrameMetrics", "(FFFFFFFZIIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;"); - jSyncViewportInfo = getMethod("syncViewportInfo", "(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;"); +void GeckoLayerClient::InitStubs(JNIEnv *env) { + mGeckoLayerClientClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/GeckoLayerClient"); + jActivateProgram = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "activateProgram", "()V"); + jContentDocumentChanged = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "contentDocumentChanged", "()V"); + jCreateFrame = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "createFrame", "()Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;"); + jDeactivateProgramAndRestoreState = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "deactivateProgramAndRestoreState", "(ZIIII)V"); + jGetDisplayPort = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "getDisplayPort", "(ZZILorg/mozilla/gecko/gfx/ImmutableViewportMetrics;)Lorg/mozilla/gecko/gfx/DisplayPortMetrics;"); + jIsContentDocumentDisplayed = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "isContentDocumentDisplayed", "()Z"); + jProgressiveUpdateCallback = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "progressiveUpdateCallback", "(ZFFFFFZ)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;"); + jSetFirstPaintViewport = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "setFirstPaintViewport", "(FFFFFFF)V"); + jSetPageRect = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "setPageRect", "(FFFF)V"); + jSyncFrameMetrics = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "syncFrameMetrics", "(FFFFFFFZIIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;"); + jSyncViewportInfo = AndroidBridge::GetMethodID(env, mGeckoLayerClientClass, "syncViewportInfo", "(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;"); } GeckoLayerClient* GeckoLayerClient::Wrap(jobject obj) { @@ -1931,11 +1913,9 @@ } jclass ImmutableViewportMetrics::mImmutableViewportMetricsClass = 0; jmethodID ImmutableViewportMetrics::jImmutableViewportMetrics = 0; -void ImmutableViewportMetrics::InitStubs(JNIEnv *jEnv) { - initInit(); - - mImmutableViewportMetricsClass = getClassGlobalRef("org/mozilla/gecko/gfx/ImmutableViewportMetrics"); - jImmutableViewportMetrics = getMethod("", "(FFFFFFFFFFFFF)V"); +void ImmutableViewportMetrics::InitStubs(JNIEnv *env) { + mImmutableViewportMetricsClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/ImmutableViewportMetrics"); + jImmutableViewportMetrics = AndroidBridge::GetMethodID(env, mImmutableViewportMetricsClass, "", "(FFFFFFFFFFFFF)V"); } ImmutableViewportMetrics* ImmutableViewportMetrics::Wrap(jobject obj) { @@ -1972,11 +1952,9 @@ } jclass LayerView::mLayerViewClass = 0; jmethodID LayerView::jRegisterCompositorWrapper = 0; -void LayerView::InitStubs(JNIEnv *jEnv) { - initInit(); - - mLayerViewClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerView"); - jRegisterCompositorWrapper = getStaticMethod("registerCxxCompositor", "()Lorg/mozilla/gecko/gfx/GLController;"); +void LayerView::InitStubs(JNIEnv *env) { + mLayerViewClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/LayerView"); + jRegisterCompositorWrapper = AndroidBridge::GetStaticMethodID(env, mLayerViewClass, "registerCxxCompositor", "()Lorg/mozilla/gecko/gfx/GLController;"); } LayerView* LayerView::Wrap(jobject obj) { @@ -2000,11 +1978,9 @@ } jclass NativePanZoomController::mNativePanZoomControllerClass = 0; jmethodID NativePanZoomController::jRequestContentRepaintWrapper = 0; -void NativePanZoomController::InitStubs(JNIEnv *jEnv) { - initInit(); - - mNativePanZoomControllerClass = getClassGlobalRef("org/mozilla/gecko/gfx/NativePanZoomController"); - jRequestContentRepaintWrapper = getMethod("requestContentRepaint", "(FFFFF)V"); +void NativePanZoomController::InitStubs(JNIEnv *env) { + mNativePanZoomControllerClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/NativePanZoomController"); + jRequestContentRepaintWrapper = AndroidBridge::GetMethodID(env, mNativePanZoomControllerClass, "requestContentRepaint", "(FFFFF)V"); } NativePanZoomController* NativePanZoomController::Wrap(jobject obj) { @@ -2039,16 +2015,14 @@ jfieldID ProgressiveUpdateData::jscale = 0; jfieldID ProgressiveUpdateData::jx = 0; jfieldID ProgressiveUpdateData::jy = 0; -void ProgressiveUpdateData::InitStubs(JNIEnv *jEnv) { - initInit(); - - mProgressiveUpdateDataClass = getClassGlobalRef("org/mozilla/gecko/gfx/ProgressiveUpdateData"); - jProgressiveUpdateData = getMethod("", "()V"); - jsetViewport = getMethod("setViewport", "(Lorg/mozilla/gecko/gfx/ImmutableViewportMetrics;)V"); - jabort = getField("abort", "Z"); - jscale = getField("scale", "F"); - jx = getField("x", "F"); - jy = getField("y", "F"); +void ProgressiveUpdateData::InitStubs(JNIEnv *env) { + mProgressiveUpdateDataClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/ProgressiveUpdateData"); + jProgressiveUpdateData = AndroidBridge::GetMethodID(env, mProgressiveUpdateDataClass, "", "()V"); + jsetViewport = AndroidBridge::GetMethodID(env, mProgressiveUpdateDataClass, "setViewport", "(Lorg/mozilla/gecko/gfx/ImmutableViewportMetrics;)V"); + jabort = AndroidBridge::GetFieldID(env, mProgressiveUpdateDataClass, "abort", "Z"); + jscale = AndroidBridge::GetFieldID(env, mProgressiveUpdateDataClass, "scale", "F"); + jx = AndroidBridge::GetFieldID(env, mProgressiveUpdateDataClass, "x", "F"); + jy = AndroidBridge::GetFieldID(env, mProgressiveUpdateDataClass, "y", "F"); } ProgressiveUpdateData* ProgressiveUpdateData::Wrap(jobject obj) { @@ -2131,20 +2105,18 @@ jfieldID ViewTransform::jscale = 0; jfieldID ViewTransform::jx = 0; jfieldID ViewTransform::jy = 0; -void ViewTransform::InitStubs(JNIEnv *jEnv) { - initInit(); - - mViewTransformClass = getClassGlobalRef("org/mozilla/gecko/gfx/ViewTransform"); - jViewTransform = getMethod("", "(FFF)V"); - jfixedLayerMarginBottom = getField("fixedLayerMarginBottom", "F"); - jfixedLayerMarginLeft = getField("fixedLayerMarginLeft", "F"); - jfixedLayerMarginRight = getField("fixedLayerMarginRight", "F"); - jfixedLayerMarginTop = getField("fixedLayerMarginTop", "F"); - joffsetX = getField("offsetX", "F"); - joffsetY = getField("offsetY", "F"); - jscale = getField("scale", "F"); - jx = getField("x", "F"); - jy = getField("y", "F"); +void ViewTransform::InitStubs(JNIEnv *env) { + mViewTransformClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/gfx/ViewTransform"); + jViewTransform = AndroidBridge::GetMethodID(env, mViewTransformClass, "", "(FFF)V"); + jfixedLayerMarginBottom = AndroidBridge::GetFieldID(env, mViewTransformClass, "fixedLayerMarginBottom", "F"); + jfixedLayerMarginLeft = AndroidBridge::GetFieldID(env, mViewTransformClass, "fixedLayerMarginLeft", "F"); + jfixedLayerMarginRight = AndroidBridge::GetFieldID(env, mViewTransformClass, "fixedLayerMarginRight", "F"); + jfixedLayerMarginTop = AndroidBridge::GetFieldID(env, mViewTransformClass, "fixedLayerMarginTop", "F"); + joffsetX = AndroidBridge::GetFieldID(env, mViewTransformClass, "offsetX", "F"); + joffsetY = AndroidBridge::GetFieldID(env, mViewTransformClass, "offsetY", "F"); + jscale = AndroidBridge::GetFieldID(env, mViewTransformClass, "scale", "F"); + jx = AndroidBridge::GetFieldID(env, mViewTransformClass, "x", "F"); + jy = AndroidBridge::GetFieldID(env, mViewTransformClass, "y", "F"); } ViewTransform* ViewTransform::Wrap(jobject obj) { @@ -2261,11 +2233,9 @@ } jclass NativeZip::mNativeZipClass = 0; jmethodID NativeZip::jCreateInputStream = 0; -void NativeZip::InitStubs(JNIEnv *jEnv) { - initInit(); - - mNativeZipClass = getClassGlobalRef("org/mozilla/gecko/mozglue/NativeZip"); - jCreateInputStream = getMethod("createInputStream", "(Ljava/nio/ByteBuffer;I)Ljava/io/InputStream;"); +void NativeZip::InitStubs(JNIEnv *env) { + mNativeZipClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/mozglue/NativeZip"); + jCreateInputStream = AndroidBridge::GetMethodID(env, mNativeZipClass, "createInputStream", "(Ljava/nio/ByteBuffer;I)Ljava/io/InputStream;"); } NativeZip* NativeZip::Wrap(jobject obj) { @@ -2293,15 +2263,13 @@ jmethodID MatrixBlobCursor::jAddRow = 0; jmethodID MatrixBlobCursor::jAddRow1 = 0; jmethodID MatrixBlobCursor::jAddRow2 = 0; -void MatrixBlobCursor::InitStubs(JNIEnv *jEnv) { - initInit(); - - mMatrixBlobCursorClass = getClassGlobalRef("org/mozilla/gecko/sqlite/MatrixBlobCursor"); - jMatrixBlobCursor = getMethod("", "([Ljava/lang/String;)V"); - jMatrixBlobCursor0 = getMethod("", "([Ljava/lang/String;I)V"); - jAddRow = getMethod("addRow", "(Ljava/lang/Iterable;)V"); - jAddRow1 = getMethod("addRow", "(Ljava/util/ArrayList;I)V"); - jAddRow2 = getMethod("addRow", "([Ljava/lang/Object;)V"); +void MatrixBlobCursor::InitStubs(JNIEnv *env) { + mMatrixBlobCursorClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/sqlite/MatrixBlobCursor"); + jMatrixBlobCursor = AndroidBridge::GetMethodID(env, mMatrixBlobCursorClass, "", "([Ljava/lang/String;)V"); + jMatrixBlobCursor0 = AndroidBridge::GetMethodID(env, mMatrixBlobCursorClass, "", "([Ljava/lang/String;I)V"); + jAddRow = AndroidBridge::GetMethodID(env, mMatrixBlobCursorClass, "addRow", "(Ljava/lang/Iterable;)V"); + jAddRow1 = AndroidBridge::GetMethodID(env, mMatrixBlobCursorClass, "addRow", "(Ljava/util/ArrayList;I)V"); + jAddRow2 = AndroidBridge::GetMethodID(env, mMatrixBlobCursorClass, "addRow", "([Ljava/lang/Object;)V"); } MatrixBlobCursor* MatrixBlobCursor::Wrap(jobject obj) { @@ -2372,13 +2340,11 @@ jmethodID SQLiteBridgeException::jSQLiteBridgeException = 0; jmethodID SQLiteBridgeException::jSQLiteBridgeException0 = 0; jfieldID SQLiteBridgeException::jserialVersionUID = 0; -void SQLiteBridgeException::InitStubs(JNIEnv *jEnv) { - initInit(); - - mSQLiteBridgeExceptionClass = getClassGlobalRef("org/mozilla/gecko/sqlite/SQLiteBridgeException"); - jSQLiteBridgeException = getMethod("", "()V"); - jSQLiteBridgeException0 = getMethod("", "(Ljava/lang/String;)V"); - jserialVersionUID = getStaticField("serialVersionUID", "J"); +void SQLiteBridgeException::InitStubs(JNIEnv *env) { + mSQLiteBridgeExceptionClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/sqlite/SQLiteBridgeException"); + jSQLiteBridgeException = AndroidBridge::GetMethodID(env, mSQLiteBridgeExceptionClass, "", "()V"); + jSQLiteBridgeException0 = AndroidBridge::GetMethodID(env, mSQLiteBridgeExceptionClass, "", "(Ljava/lang/String;)V"); + jserialVersionUID = AndroidBridge::GetStaticFieldID(env, mSQLiteBridgeExceptionClass, "serialVersionUID", "J"); } SQLiteBridgeException* SQLiteBridgeException::Wrap(jobject obj) { @@ -2421,14 +2387,12 @@ jmethodID Clipboard::jGetClipboardTextWrapper = 0; jmethodID Clipboard::jHasText = 0; jmethodID Clipboard::jSetClipboardText = 0; -void Clipboard::InitStubs(JNIEnv *jEnv) { - initInit(); - - mClipboardClass = getClassGlobalRef("org/mozilla/gecko/util/Clipboard"); - jClearText = getStaticMethod("clearText", "()V"); - jGetClipboardTextWrapper = getStaticMethod("getText", "()Ljava/lang/String;"); - jHasText = getStaticMethod("hasText", "()Z"); - jSetClipboardText = getStaticMethod("setText", "(Ljava/lang/CharSequence;)V"); +void Clipboard::InitStubs(JNIEnv *env) { + mClipboardClass = AndroidBridge::GetClassGlobalRef(env, "org/mozilla/gecko/util/Clipboard"); + jClearText = AndroidBridge::GetStaticMethodID(env, mClipboardClass, "clearText", "()V"); + jGetClipboardTextWrapper = AndroidBridge::GetStaticMethodID(env, mClipboardClass, "getText", "()Ljava/lang/String;"); + jHasText = AndroidBridge::GetStaticMethodID(env, mClipboardClass, "hasText", "()Z"); + jSetClipboardText = AndroidBridge::GetStaticMethodID(env, mClipboardClass, "setText", "(Ljava/lang/CharSequence;)V"); } Clipboard* Clipboard::Wrap(jobject obj) { @@ -2490,25 +2454,25 @@ env->PopLocalFrame(nullptr); } -void InitStubs(JNIEnv *jEnv) { - DownloadsIntegration::InitStubs(jEnv); - GeckoAppShell::InitStubs(jEnv); - GeckoJavaSampler::InitStubs(jEnv); - RestrictedProfiles::InitStubs(jEnv); - SurfaceBits::InitStubs(jEnv); - ThumbnailHelper::InitStubs(jEnv); - DisplayPortMetrics::InitStubs(jEnv); - GLController::InitStubs(jEnv); - GeckoLayerClient::InitStubs(jEnv); - ImmutableViewportMetrics::InitStubs(jEnv); - LayerView::InitStubs(jEnv); - NativePanZoomController::InitStubs(jEnv); - ProgressiveUpdateData::InitStubs(jEnv); - ViewTransform::InitStubs(jEnv); - NativeZip::InitStubs(jEnv); - MatrixBlobCursor::InitStubs(jEnv); - SQLiteBridgeException::InitStubs(jEnv); - Clipboard::InitStubs(jEnv); +void InitStubs(JNIEnv *env) { + DownloadsIntegration::InitStubs(env); + GeckoAppShell::InitStubs(env); + GeckoJavaSampler::InitStubs(env); + RestrictedProfiles::InitStubs(env); + SurfaceBits::InitStubs(env); + ThumbnailHelper::InitStubs(env); + DisplayPortMetrics::InitStubs(env); + GLController::InitStubs(env); + GeckoLayerClient::InitStubs(env); + ImmutableViewportMetrics::InitStubs(env); + LayerView::InitStubs(env); + NativePanZoomController::InitStubs(env); + ProgressiveUpdateData::InitStubs(env); + ViewTransform::InitStubs(env); + NativeZip::InitStubs(env); + MatrixBlobCursor::InitStubs(env); + SQLiteBridgeException::InitStubs(env); + Clipboard::InitStubs(env); } } /* android */ } /* widget */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedJNIWrappers.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedJNIWrappers.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedJNIWrappers.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedJNIWrappers.h 2014-11-26 21:46:06.000000000 +0000 @@ -12,11 +12,11 @@ namespace mozilla { namespace widget { namespace android { -void InitStubs(JNIEnv *jEnv); +void InitStubs(JNIEnv *env); class DownloadsIntegration : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static DownloadsIntegration* Wrap(jobject obj); DownloadsIntegration(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static void ScanMedia(const nsAString& a0, const nsAString& a1); @@ -28,7 +28,7 @@ class GeckoAppShell : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static GeckoAppShell* Wrap(jobject obj); GeckoAppShell(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static void AcknowledgeEvent(); @@ -202,7 +202,7 @@ class GeckoJavaSampler : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static GeckoJavaSampler* Wrap(jobject obj); GeckoJavaSampler(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static jstring GetFrameNameJavaProfilingWrapper(int32_t a0, int32_t a1, int32_t a2); @@ -226,7 +226,7 @@ class RestrictedProfiles : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static RestrictedProfiles* Wrap(jobject obj); RestrictedProfiles(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static jstring GetUserRestrictions(); @@ -242,7 +242,7 @@ class SurfaceBits : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static SurfaceBits* Wrap(jobject obj); SurfaceBits(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; SurfaceBits(); @@ -265,7 +265,7 @@ class ThumbnailHelper : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static ThumbnailHelper* Wrap(jobject obj); ThumbnailHelper(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static void SendThumbnail(jobject a0, int32_t a1, bool a2, bool a3); @@ -277,7 +277,7 @@ class DisplayPortMetrics : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static DisplayPortMetrics* Wrap(jobject obj); DisplayPortMetrics(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; DisplayPortMetrics(jfloat a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4); @@ -293,7 +293,7 @@ class GLController : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static GLController* Wrap(jobject obj); GLController(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; jobject CreateEGLSurfaceForCompositorWrapper(); @@ -305,7 +305,7 @@ class GeckoLayerClient : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static GeckoLayerClient* Wrap(jobject obj); GeckoLayerClient(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; void ActivateProgram(); @@ -337,7 +337,7 @@ class ImmutableViewportMetrics : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static ImmutableViewportMetrics* Wrap(jobject obj); ImmutableViewportMetrics(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; ImmutableViewportMetrics(jfloat a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4, jfloat a5, jfloat a6, jfloat a7, jfloat a8, jfloat a9, jfloat a10, jfloat a11, jfloat a12); @@ -349,7 +349,7 @@ class LayerView : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static LayerView* Wrap(jobject obj); LayerView(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static jobject RegisterCompositorWrapper(); @@ -361,7 +361,7 @@ class NativePanZoomController : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static NativePanZoomController* Wrap(jobject obj); NativePanZoomController(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; void RequestContentRepaintWrapper(jfloat a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4); @@ -373,7 +373,7 @@ class ProgressiveUpdateData : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static ProgressiveUpdateData* Wrap(jobject obj); ProgressiveUpdateData(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; ProgressiveUpdateData(); @@ -398,7 +398,7 @@ class ViewTransform : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static ViewTransform* Wrap(jobject obj); ViewTransform(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; ViewTransform(jfloat a0, jfloat a1, jfloat a2); @@ -437,7 +437,7 @@ class NativeZip : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static NativeZip* Wrap(jobject obj); NativeZip(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; jobject CreateInputStream(jobject a0, int32_t a1); @@ -449,7 +449,7 @@ class MatrixBlobCursor : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static MatrixBlobCursor* Wrap(jobject obj); MatrixBlobCursor(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; MatrixBlobCursor(jobjectArray a0); @@ -469,7 +469,7 @@ class SQLiteBridgeException : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static SQLiteBridgeException* Wrap(jobject obj); SQLiteBridgeException(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; SQLiteBridgeException(); @@ -484,7 +484,7 @@ class Clipboard : public AutoGlobalWrappedJavaObject { public: - static void InitStubs(JNIEnv *jEnv); + static void InitStubs(JNIEnv *env); static Clipboard* Wrap(jobject obj); Clipboard(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; static void ClearText(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedSDKWrappers.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedSDKWrappers.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedSDKWrappers.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedSDKWrappers.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1877 +0,0 @@ -// GENERATED CODE -// Generated by the Java program at /build/jarClassProcessors at compile time from -// a given set of jars and a set of requested methods. To update, change the annotations -// on the corresponding Java methods and rerun the build. Manually updating this file -// will cause your build to fail. - -#include "GeneratedSDKWrappers.h" -#include "AndroidBridgeUtilities.h" -#include "nsXPCOMStrings.h" -#include "AndroidBridge.h" -#include "nsDebug.h" - -namespace mozilla { -namespace widget { -namespace android { -jclass MediaCodec::mMediaCodecClass = 0; -jmethodID MediaCodec::jConfigure = 0; -jmethodID MediaCodec::jCreateByCodecName = 0; -jmethodID MediaCodec::jCreateDecoderByType = 0; -jmethodID MediaCodec::jCreateEncoderByType = 0; -jmethodID MediaCodec::jDequeueInputBuffer = 0; -jmethodID MediaCodec::jDequeueOutputBuffer = 0; -jmethodID MediaCodec::jFinalize = 0; -jmethodID MediaCodec::jFlush = 0; -jmethodID MediaCodec::jGetInputBuffers = 0; -jmethodID MediaCodec::jGetOutputBuffers = 0; -jmethodID MediaCodec::jGetOutputFormat = 0; -jmethodID MediaCodec::jQueueInputBuffer = 0; -jmethodID MediaCodec::jQueueSecureInputBuffer = 0; -jmethodID MediaCodec::jRelease = 0; -jmethodID MediaCodec::jReleaseOutputBuffer = 0; -jmethodID MediaCodec::jSetVideoScalingMode = 0; -jmethodID MediaCodec::jStart = 0; -jmethodID MediaCodec::jStop = 0; -jfieldID MediaCodec::jBUFFER_FLAG_CODEC_CONFIG = 0; -jfieldID MediaCodec::jBUFFER_FLAG_END_OF_STREAM = 0; -jfieldID MediaCodec::jBUFFER_FLAG_SYNC_FRAME = 0; -jfieldID MediaCodec::jCONFIGURE_FLAG_ENCODE = 0; -jfieldID MediaCodec::jCRYPTO_MODE_AES_CTR = 0; -jfieldID MediaCodec::jCRYPTO_MODE_UNENCRYPTED = 0; -jfieldID MediaCodec::jINFO_OUTPUT_BUFFERS_CHANGED = 0; -jfieldID MediaCodec::jINFO_OUTPUT_FORMAT_CHANGED = 0; -jfieldID MediaCodec::jINFO_TRY_AGAIN_LATER = 0; -jfieldID MediaCodec::jVIDEO_SCALING_MODE_SCALE_TO_FIT = 0; -jfieldID MediaCodec::jVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 0; -void MediaCodec::InitStubs(JNIEnv *jEnv) { - initInit(); - - mMediaCodecClass = getClassGlobalRef("android/media/MediaCodec"); - jConfigure = getMethod("configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V"); - jCreateByCodecName = getStaticMethod("createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;"); - jCreateDecoderByType = getStaticMethod("createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;"); - jCreateEncoderByType = getStaticMethod("createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;"); - jDequeueInputBuffer = getMethod("dequeueInputBuffer", "(J)I"); - jDequeueOutputBuffer = getMethod("dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I"); - jFinalize = getMethod("finalize", "()V"); - jFlush = getMethod("flush", "()V"); - jGetInputBuffers = getMethod("getInputBuffers", "()[Ljava/nio/ByteBuffer;"); - jGetOutputBuffers = getMethod("getOutputBuffers", "()[Ljava/nio/ByteBuffer;"); - jGetOutputFormat = getMethod("getOutputFormat", "()Landroid/media/MediaFormat;"); - jQueueInputBuffer = getMethod("queueInputBuffer", "(IIIJI)V"); - jQueueSecureInputBuffer = getMethod("queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V"); - jRelease = getMethod("release", "()V"); - jReleaseOutputBuffer = getMethod("releaseOutputBuffer", "(IZ)V"); - jSetVideoScalingMode = getMethod("setVideoScalingMode", "(I)V"); - jStart = getMethod("start", "()V"); - jStop = getMethod("stop", "()V"); - jBUFFER_FLAG_CODEC_CONFIG = getStaticField("BUFFER_FLAG_CODEC_CONFIG", "I"); - jBUFFER_FLAG_END_OF_STREAM = getStaticField("BUFFER_FLAG_END_OF_STREAM", "I"); - jBUFFER_FLAG_SYNC_FRAME = getStaticField("BUFFER_FLAG_SYNC_FRAME", "I"); - jCONFIGURE_FLAG_ENCODE = getStaticField("CONFIGURE_FLAG_ENCODE", "I"); - jCRYPTO_MODE_AES_CTR = getStaticField("CRYPTO_MODE_AES_CTR", "I"); - jCRYPTO_MODE_UNENCRYPTED = getStaticField("CRYPTO_MODE_UNENCRYPTED", "I"); - jINFO_OUTPUT_BUFFERS_CHANGED = getStaticField("INFO_OUTPUT_BUFFERS_CHANGED", "I"); - jINFO_OUTPUT_FORMAT_CHANGED = getStaticField("INFO_OUTPUT_FORMAT_CHANGED", "I"); - jINFO_TRY_AGAIN_LATER = getStaticField("INFO_TRY_AGAIN_LATER", "I"); - jVIDEO_SCALING_MODE_SCALE_TO_FIT = getStaticField("VIDEO_SCALING_MODE_SCALE_TO_FIT", "I"); - jVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = getStaticField("VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING", "I"); -} - -MediaCodec* MediaCodec::Wrap(jobject obj) { - JNIEnv *env = GetJNIForThread(); - MediaCodec* ret = new MediaCodec(obj, env); - env->DeleteLocalRef(obj); - return ret; -} - -bool MediaCodec::Configure(jobject a0, jobject a1, jobject a2, int32_t a3) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(3) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[4]; - args[0].l = a0; - args[1].l = a1; - args[2].l = a2; - args[3].i = a3; - - env->CallVoidMethodA(wrapped_obj, jConfigure, args); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - env->PopLocalFrame(nullptr); - return false; - } - env->PopLocalFrame(nullptr); - return true; -} - -jobject MediaCodec::CreateByCodecName(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - jobject temp = env->CallStaticObjectMethod(mMediaCodecClass, jCreateByCodecName, j0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject MediaCodec::CreateDecoderByType(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - jobject temp = env->CallStaticObjectMethod(mMediaCodecClass, jCreateDecoderByType, j0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject MediaCodec::CreateEncoderByType(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - jobject temp = env->CallStaticObjectMethod(mMediaCodecClass, jCreateEncoderByType, j0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -int32_t MediaCodec::DequeueInputBuffer(int64_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jDequeueInputBuffer, a0); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - env->PopLocalFrame(nullptr); - return MEDIACODEC_EXCEPTION_INDEX; - } - env->PopLocalFrame(nullptr); - return temp; -} - -int32_t MediaCodec::DequeueOutputBuffer(jobject a0, int64_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jDequeueOutputBuffer, a0, a1); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - env->PopLocalFrame(nullptr); - return MEDIACODEC_EXCEPTION_INDEX; - } - env->PopLocalFrame(nullptr); - return temp; -} - -void MediaCodec::Finalize() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jFinalize); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaCodec::Flush() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jFlush); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -jobjectArray MediaCodec::GetInputBuffers() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jGetInputBuffers); - AndroidBridge::HandleUncaughtException(env); - jobjectArray ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobjectArray MediaCodec::GetOutputBuffers() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jGetOutputBuffers); - AndroidBridge::HandleUncaughtException(env); - jobjectArray ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject MediaCodec::GetOutputFormat() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jGetOutputFormat); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -void MediaCodec::QueueInputBuffer(int32_t a0, int32_t a1, int32_t a2, int64_t a3, int32_t a4) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(5) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[5]; - args[0].i = a0; - args[1].i = a1; - args[2].i = a2; - args[3].j = a3; - args[4].i = a4; - - env->CallVoidMethodA(wrapped_obj, jQueueInputBuffer, args); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaCodec::QueueSecureInputBuffer(int32_t a0, int32_t a1, jobject a2, int64_t a3, int32_t a4) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[5]; - args[0].i = a0; - args[1].i = a1; - args[2].l = a2; - args[3].j = a3; - args[4].i = a4; - - env->CallVoidMethodA(wrapped_obj, jQueueSecureInputBuffer, args); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaCodec::Release() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jRelease); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaCodec::ReleaseOutputBuffer(int32_t a0, bool a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jReleaseOutputBuffer, a0, a1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaCodec::SetVideoScalingMode(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jSetVideoScalingMode, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -bool MediaCodec::Start() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jStart); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - env->PopLocalFrame(nullptr); - return false; - } - env->PopLocalFrame(nullptr); - return true; -} - -void MediaCodec::Stop() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, jStop); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -int32_t MediaCodec::getBUFFER_FLAG_CODEC_CONFIG() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jBUFFER_FLAG_CODEC_CONFIG); -} - -int32_t MediaCodec::getBUFFER_FLAG_END_OF_STREAM() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jBUFFER_FLAG_END_OF_STREAM); -} - -int32_t MediaCodec::getBUFFER_FLAG_SYNC_FRAME() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jBUFFER_FLAG_SYNC_FRAME); -} - -int32_t MediaCodec::getCONFIGURE_FLAG_ENCODE() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jCONFIGURE_FLAG_ENCODE); -} - -int32_t MediaCodec::getCRYPTO_MODE_AES_CTR() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jCRYPTO_MODE_AES_CTR); -} - -int32_t MediaCodec::getCRYPTO_MODE_UNENCRYPTED() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jCRYPTO_MODE_UNENCRYPTED); -} - -int32_t MediaCodec::getINFO_OUTPUT_BUFFERS_CHANGED() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jINFO_OUTPUT_BUFFERS_CHANGED); -} - -int32_t MediaCodec::getINFO_OUTPUT_FORMAT_CHANGED() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jINFO_OUTPUT_FORMAT_CHANGED); -} - -int32_t MediaCodec::getINFO_TRY_AGAIN_LATER() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jINFO_TRY_AGAIN_LATER); -} - -int32_t MediaCodec::getVIDEO_SCALING_MODE_SCALE_TO_FIT() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jVIDEO_SCALING_MODE_SCALE_TO_FIT); -} - -int32_t MediaCodec::getVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING() { - JNIEnv *env = GetJNIForThread(); - return env->GetStaticIntField(mMediaCodecClass, jVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); -} -jclass MediaFormat::mMediaFormatClass = 0; -jmethodID MediaFormat::jMediaFormat = 0; -jmethodID MediaFormat::jContainsKey = 0; -jmethodID MediaFormat::jCreateAudioFormat = 0; -jmethodID MediaFormat::jCreateVideoFormat = 0; -jmethodID MediaFormat::jGetByteBuffer = 0; -jmethodID MediaFormat::jGetFloat = 0; -jmethodID MediaFormat::jGetInteger = 0; -jmethodID MediaFormat::jGetLong = 0; -jmethodID MediaFormat::jGetString = 0; -jmethodID MediaFormat::jSetByteBuffer = 0; -jmethodID MediaFormat::jSetFloat = 0; -jmethodID MediaFormat::jSetInteger = 0; -jmethodID MediaFormat::jSetLong = 0; -jmethodID MediaFormat::jSetString = 0; -jmethodID MediaFormat::jToString = 0; -jfieldID MediaFormat::jKEY_AAC_PROFILE = 0; -jfieldID MediaFormat::jKEY_BIT_RATE = 0; -jfieldID MediaFormat::jKEY_CHANNEL_COUNT = 0; -jfieldID MediaFormat::jKEY_CHANNEL_MASK = 0; -jfieldID MediaFormat::jKEY_COLOR_FORMAT = 0; -jfieldID MediaFormat::jKEY_DURATION = 0; -jfieldID MediaFormat::jKEY_FLAC_COMPRESSION_LEVEL = 0; -jfieldID MediaFormat::jKEY_FRAME_RATE = 0; -jfieldID MediaFormat::jKEY_HEIGHT = 0; -jfieldID MediaFormat::jKEY_IS_ADTS = 0; -jfieldID MediaFormat::jKEY_I_FRAME_INTERVAL = 0; -jfieldID MediaFormat::jKEY_MAX_INPUT_SIZE = 0; -jfieldID MediaFormat::jKEY_MIME = 0; -jfieldID MediaFormat::jKEY_SAMPLE_RATE = 0; -jfieldID MediaFormat::jKEY_WIDTH = 0; -void MediaFormat::InitStubs(JNIEnv *jEnv) { - initInit(); - - mMediaFormatClass = getClassGlobalRef("android/media/MediaFormat"); - jMediaFormat = getMethod("", "()V"); - jContainsKey = getMethod("containsKey", "(Ljava/lang/String;)Z"); - jCreateAudioFormat = getStaticMethod("createAudioFormat", "(Ljava/lang/String;II)Landroid/media/MediaFormat;"); - jCreateVideoFormat = getStaticMethod("createVideoFormat", "(Ljava/lang/String;II)Landroid/media/MediaFormat;"); - jGetByteBuffer = getMethod("getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;"); - jGetFloat = getMethod("getFloat", "(Ljava/lang/String;)F"); - jGetInteger = getMethod("getInteger", "(Ljava/lang/String;)I"); - jGetLong = getMethod("getLong", "(Ljava/lang/String;)J"); - jGetString = getMethod("getString", "(Ljava/lang/String;)Ljava/lang/String;"); - jSetByteBuffer = getMethod("setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V"); - jSetFloat = getMethod("setFloat", "(Ljava/lang/String;F)V"); - jSetInteger = getMethod("setInteger", "(Ljava/lang/String;I)V"); - jSetLong = getMethod("setLong", "(Ljava/lang/String;J)V"); - jSetString = getMethod("setString", "(Ljava/lang/String;Ljava/lang/String;)V"); - jToString = getMethod("toString", "()Ljava/lang/String;"); - jKEY_AAC_PROFILE = getStaticField("KEY_AAC_PROFILE", "Ljava/lang/String;"); - jKEY_BIT_RATE = getStaticField("KEY_BIT_RATE", "Ljava/lang/String;"); - jKEY_CHANNEL_COUNT = getStaticField("KEY_CHANNEL_COUNT", "Ljava/lang/String;"); - jKEY_CHANNEL_MASK = getStaticField("KEY_CHANNEL_MASK", "Ljava/lang/String;"); - jKEY_COLOR_FORMAT = getStaticField("KEY_COLOR_FORMAT", "Ljava/lang/String;"); - jKEY_DURATION = getStaticField("KEY_DURATION", "Ljava/lang/String;"); - jKEY_FLAC_COMPRESSION_LEVEL = getStaticField("KEY_FLAC_COMPRESSION_LEVEL", "Ljava/lang/String;"); - jKEY_FRAME_RATE = getStaticField("KEY_FRAME_RATE", "Ljava/lang/String;"); - jKEY_HEIGHT = getStaticField("KEY_HEIGHT", "Ljava/lang/String;"); - jKEY_IS_ADTS = getStaticField("KEY_IS_ADTS", "Ljava/lang/String;"); - jKEY_I_FRAME_INTERVAL = getStaticField("KEY_I_FRAME_INTERVAL", "Ljava/lang/String;"); - jKEY_MAX_INPUT_SIZE = getStaticField("KEY_MAX_INPUT_SIZE", "Ljava/lang/String;"); - jKEY_MIME = getStaticField("KEY_MIME", "Ljava/lang/String;"); - jKEY_SAMPLE_RATE = getStaticField("KEY_SAMPLE_RATE", "Ljava/lang/String;"); - jKEY_WIDTH = getStaticField("KEY_WIDTH", "Ljava/lang/String;"); -} - -MediaFormat* MediaFormat::Wrap(jobject obj) { - JNIEnv *env = GetJNIForThread(); - MediaFormat* ret = new MediaFormat(obj, env); - env->DeleteLocalRef(obj); - return ret; -} - -MediaFormat::MediaFormat() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - Init(env->NewObject(mMediaFormatClass, jMediaFormat), env); - env->PopLocalFrame(nullptr); -} - -bool MediaFormat::ContainsKey(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - bool temp = env->CallBooleanMethod(wrapped_obj, jContainsKey, j0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jobject MediaFormat::CreateAudioFormat(const nsAString& a0, int32_t a1, int32_t a2) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[3]; - args[0].l = AndroidBridge::NewJavaString(env, a0); - args[1].i = a1; - args[2].i = a2; - - jobject temp = env->CallStaticObjectMethodA(mMediaFormatClass, jCreateAudioFormat, args); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject MediaFormat::CreateVideoFormat(const nsAString& a0, int32_t a1, int32_t a2) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[3]; - args[0].l = AndroidBridge::NewJavaString(env, a0); - args[1].i = a1; - args[2].i = a2; - - jobject temp = env->CallStaticObjectMethodA(mMediaFormatClass, jCreateVideoFormat, args); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject MediaFormat::GetByteBuffer(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - jobject temp = env->CallObjectMethod(wrapped_obj, jGetByteBuffer, j0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jfloat MediaFormat::GetFloat(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - jfloat temp = env->CallFloatMethod(wrapped_obj, jGetFloat, j0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int32_t MediaFormat::GetInteger(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - int32_t temp = env->CallIntMethod(wrapped_obj, jGetInteger, j0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int64_t MediaFormat::GetLong(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - int64_t temp = env->CallLongMethod(wrapped_obj, jGetLong, j0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jstring MediaFormat::GetString(const nsAString& a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - jobject temp = env->CallObjectMethod(wrapped_obj, jGetString, j0); - AndroidBridge::HandleUncaughtException(env); - jstring ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -void MediaFormat::SetByteBuffer(const nsAString& a0, jobject a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - env->CallVoidMethod(wrapped_obj, jSetByteBuffer, j0, a1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaFormat::SetFloat(const nsAString& a0, jfloat a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - env->CallVoidMethod(wrapped_obj, jSetFloat, j0, a1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaFormat::SetInteger(const nsAString& a0, int32_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - env->CallVoidMethod(wrapped_obj, jSetInteger, j0, a1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaFormat::SetLong(const nsAString& a0, int64_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - env->CallVoidMethod(wrapped_obj, jSetLong, j0, a1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -void MediaFormat::SetString(const nsAString& a0, const nsAString& a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jstring j0 = AndroidBridge::NewJavaString(env, a0); - jstring j1 = AndroidBridge::NewJavaString(env, a1); - - env->CallVoidMethod(wrapped_obj, jSetString, j0, j1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -jstring MediaFormat::ToString() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jToString); - AndroidBridge::HandleUncaughtException(env); - jstring ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jstring MediaFormat::getKEY_AAC_PROFILE() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_AAC_PROFILE)); -} - -jstring MediaFormat::getKEY_BIT_RATE() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_BIT_RATE)); -} - -jstring MediaFormat::getKEY_CHANNEL_COUNT() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_CHANNEL_COUNT)); -} - -jstring MediaFormat::getKEY_CHANNEL_MASK() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_CHANNEL_MASK)); -} - -jstring MediaFormat::getKEY_COLOR_FORMAT() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_COLOR_FORMAT)); -} - -jstring MediaFormat::getKEY_DURATION() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_DURATION)); -} - -jstring MediaFormat::getKEY_FLAC_COMPRESSION_LEVEL() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_FLAC_COMPRESSION_LEVEL)); -} - -jstring MediaFormat::getKEY_FRAME_RATE() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_FRAME_RATE)); -} - -jstring MediaFormat::getKEY_HEIGHT() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_HEIGHT)); -} - -jstring MediaFormat::getKEY_IS_ADTS() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_IS_ADTS)); -} - -jstring MediaFormat::getKEY_I_FRAME_INTERVAL() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_I_FRAME_INTERVAL)); -} - -jstring MediaFormat::getKEY_MAX_INPUT_SIZE() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_MAX_INPUT_SIZE)); -} - -jstring MediaFormat::getKEY_MIME() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_MIME)); -} - -jstring MediaFormat::getKEY_SAMPLE_RATE() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_SAMPLE_RATE)); -} - -jstring MediaFormat::getKEY_WIDTH() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetStaticObjectField(mMediaFormatClass, jKEY_WIDTH)); -} -jclass ByteBuffer::mByteBufferClass = 0; -jmethodID ByteBuffer::j_get = 0; -jmethodID ByteBuffer::j_put = 0; -jmethodID ByteBuffer::jAllocate = 0; -jmethodID ByteBuffer::jAllocateDirect = 0; -jmethodID ByteBuffer::jArray = 0; -jmethodID ByteBuffer::jArray1 = 0; -jmethodID ByteBuffer::jArrayOffset = 0; -jmethodID ByteBuffer::jAsCharBuffer = 0; -jmethodID ByteBuffer::jAsDoubleBuffer = 0; -jmethodID ByteBuffer::jAsFloatBuffer = 0; -jmethodID ByteBuffer::jAsIntBuffer = 0; -jmethodID ByteBuffer::jAsLongBuffer = 0; -jmethodID ByteBuffer::jAsReadOnlyBuffer = 0; -jmethodID ByteBuffer::jAsShortBuffer = 0; -jmethodID ByteBuffer::jCompact = 0; -jmethodID ByteBuffer::jCompareTo = 0; -jmethodID ByteBuffer::jCompareTo1 = 0; -jmethodID ByteBuffer::jDuplicate = 0; -jmethodID ByteBuffer::jEquals = 0; -jmethodID ByteBuffer::jGet = 0; -jmethodID ByteBuffer::jGet1 = 0; -jmethodID ByteBuffer::jGet10 = 0; -jmethodID ByteBuffer::jGet11 = 0; -jmethodID ByteBuffer::jGetChar = 0; -jmethodID ByteBuffer::jGetChar1 = 0; -jmethodID ByteBuffer::jGetDouble = 0; -jmethodID ByteBuffer::jGetDouble1 = 0; -jmethodID ByteBuffer::jGetFloat = 0; -jmethodID ByteBuffer::jGetFloat1 = 0; -jmethodID ByteBuffer::jGetInt = 0; -jmethodID ByteBuffer::jGetInt1 = 0; -jmethodID ByteBuffer::jGetLong = 0; -jmethodID ByteBuffer::jGetLong1 = 0; -jmethodID ByteBuffer::jGetShort = 0; -jmethodID ByteBuffer::jGetShort1 = 0; -jmethodID ByteBuffer::jHasArray = 0; -jmethodID ByteBuffer::jHashCode = 0; -jmethodID ByteBuffer::jIsDirect = 0; -jmethodID ByteBuffer::jOrder = 0; -jmethodID ByteBuffer::jOrder1 = 0; -jmethodID ByteBuffer::jPut = 0; -jmethodID ByteBuffer::jPut1 = 0; -jmethodID ByteBuffer::jPut12 = 0; -jmethodID ByteBuffer::jPut13 = 0; -jmethodID ByteBuffer::jPut14 = 0; -jmethodID ByteBuffer::jPutChar = 0; -jmethodID ByteBuffer::jPutChar1 = 0; -jmethodID ByteBuffer::jPutDouble = 0; -jmethodID ByteBuffer::jPutDouble1 = 0; -jmethodID ByteBuffer::jPutFloat = 0; -jmethodID ByteBuffer::jPutFloat1 = 0; -jmethodID ByteBuffer::jPutInt = 0; -jmethodID ByteBuffer::jPutInt1 = 0; -jmethodID ByteBuffer::jPutLong = 0; -jmethodID ByteBuffer::jPutLong1 = 0; -jmethodID ByteBuffer::jPutShort = 0; -jmethodID ByteBuffer::jPutShort1 = 0; -jmethodID ByteBuffer::jSlice = 0; -jmethodID ByteBuffer::jToString = 0; -jmethodID ByteBuffer::jWrap = 0; -jmethodID ByteBuffer::jWrap1 = 0; -jfieldID ByteBuffer::jBigEndian = 0; -jfieldID ByteBuffer::jHb = 0; -jfieldID ByteBuffer::jIsReadOnly = 0; -jfieldID ByteBuffer::jNativeByteOrder = 0; -jfieldID ByteBuffer::jOffset = 0; -void ByteBuffer::InitStubs(JNIEnv *jEnv) { - initInit(); - - mByteBufferClass = getClassGlobalRef("java/nio/ByteBuffer"); - //j_get = getMethod("_get", "(I)B"); - //j_put = getMethod("_put", "(IB)V"); - jAllocate = getStaticMethod("allocate", "(I)Ljava/nio/ByteBuffer;"); - jAllocateDirect = getStaticMethod("allocateDirect", "(I)Ljava/nio/ByteBuffer;"); - jArray = getMethod("array", "()Ljava/lang/Object;"); - jArray1 = getMethod("array", "()[B"); - jArrayOffset = getMethod("arrayOffset", "()I"); - jAsCharBuffer = getMethod("asCharBuffer", "()Ljava/nio/CharBuffer;"); - jAsDoubleBuffer = getMethod("asDoubleBuffer", "()Ljava/nio/DoubleBuffer;"); - jAsFloatBuffer = getMethod("asFloatBuffer", "()Ljava/nio/FloatBuffer;"); - jAsIntBuffer = getMethod("asIntBuffer", "()Ljava/nio/IntBuffer;"); - jAsLongBuffer = getMethod("asLongBuffer", "()Ljava/nio/LongBuffer;"); - jAsReadOnlyBuffer = getMethod("asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;"); - jAsShortBuffer = getMethod("asShortBuffer", "()Ljava/nio/ShortBuffer;"); - jCompact = getMethod("compact", "()Ljava/nio/ByteBuffer;"); - jCompareTo = getMethod("compareTo", "(Ljava/lang/Object;)I"); - jCompareTo1 = getMethod("compareTo", "(Ljava/nio/ByteBuffer;)I"); - jDuplicate = getMethod("duplicate", "()Ljava/nio/ByteBuffer;"); - jEquals = getMethod("equals", "(Ljava/lang/Object;)Z"); - jGet = getMethod("get", "()B"); - jGet1 = getMethod("get", "(I)B"); - jGet10 = getMethod("get", "([B)Ljava/nio/ByteBuffer;"); - jGet11 = getMethod("get", "([BII)Ljava/nio/ByteBuffer;"); - jGetChar = getMethod("getChar", "()C"); - jGetChar1 = getMethod("getChar", "(I)C"); - jGetDouble = getMethod("getDouble", "()D"); - jGetDouble1 = getMethod("getDouble", "(I)D"); - jGetFloat = getMethod("getFloat", "()F"); - jGetFloat1 = getMethod("getFloat", "(I)F"); - jGetInt = getMethod("getInt", "()I"); - jGetInt1 = getMethod("getInt", "(I)I"); - jGetLong = getMethod("getLong", "()J"); - jGetLong1 = getMethod("getLong", "(I)J"); - jGetShort = getMethod("getShort", "()S"); - jGetShort1 = getMethod("getShort", "(I)S"); - jHasArray = getMethod("hasArray", "()Z"); - jHashCode = getMethod("hashCode", "()I"); - jIsDirect = getMethod("isDirect", "()Z"); - jOrder = getMethod("order", "()Ljava/nio/ByteOrder;"); - jOrder1 = getMethod("order", "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"); - jPut = getMethod("put", "(B)Ljava/nio/ByteBuffer;"); - jPut1 = getMethod("put", "(IB)Ljava/nio/ByteBuffer;"); - jPut12 = getMethod("put", "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;"); - jPut13 = getMethod("put", "([B)Ljava/nio/ByteBuffer;"); - jPut14 = getMethod("put", "([BII)Ljava/nio/ByteBuffer;"); - jPutChar = getMethod("putChar", "(C)Ljava/nio/ByteBuffer;"); - jPutChar1 = getMethod("putChar", "(IC)Ljava/nio/ByteBuffer;"); - jPutDouble = getMethod("putDouble", "(D)Ljava/nio/ByteBuffer;"); - jPutDouble1 = getMethod("putDouble", "(ID)Ljava/nio/ByteBuffer;"); - jPutFloat = getMethod("putFloat", "(F)Ljava/nio/ByteBuffer;"); - jPutFloat1 = getMethod("putFloat", "(IF)Ljava/nio/ByteBuffer;"); - jPutInt = getMethod("putInt", "(I)Ljava/nio/ByteBuffer;"); - jPutInt1 = getMethod("putInt", "(II)Ljava/nio/ByteBuffer;"); - jPutLong = getMethod("putLong", "(IJ)Ljava/nio/ByteBuffer;"); - jPutLong1 = getMethod("putLong", "(J)Ljava/nio/ByteBuffer;"); - jPutShort = getMethod("putShort", "(IS)Ljava/nio/ByteBuffer;"); - jPutShort1 = getMethod("putShort", "(S)Ljava/nio/ByteBuffer;"); - jSlice = getMethod("slice", "()Ljava/nio/ByteBuffer;"); - jToString = getMethod("toString", "()Ljava/lang/String;"); - jWrap = getStaticMethod("wrap", "([B)Ljava/nio/ByteBuffer;"); - jWrap1 = getStaticMethod("wrap", "([BII)Ljava/nio/ByteBuffer;"); - /* - jBigEndian = getField("bigEndian", "Z"); - jHb = getField("hb", "[B"); - jIsReadOnly = getField("isReadOnly", "Z"); - jNativeByteOrder = getField("nativeByteOrder", "Z"); - jOffset = getField("offset", "I"); - */ -} - -ByteBuffer* ByteBuffer::Wrap(jobject obj) { - JNIEnv *env = GetJNIForThread(); - ByteBuffer* ret = new ByteBuffer(obj, env); - env->DeleteLocalRef(obj); - return ret; -} - -int8_t ByteBuffer::_get(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int8_t temp = env->CallByteMethod(wrapped_obj, j_get, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -void ByteBuffer::_put(int32_t a0, int8_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - env->CallVoidMethod(wrapped_obj, j_put, a0, a1); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -jobject ByteBuffer::Allocate(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallStaticObjectMethod(mByteBufferClass, jAllocate, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AllocateDirect(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallStaticObjectMethod(mByteBufferClass, jAllocateDirect, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Array() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jArray); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jbyteArray ByteBuffer::Array1() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jArray1); - AndroidBridge::HandleUncaughtException(env); - jbyteArray ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -int32_t ByteBuffer::ArrayOffset() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jArrayOffset); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jstring ByteBuffer::AsCharBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsCharBuffer); - AndroidBridge::HandleUncaughtException(env); - jstring ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AsDoubleBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsDoubleBuffer); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AsFloatBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsFloatBuffer); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AsIntBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsIntBuffer); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AsLongBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsLongBuffer); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AsReadOnlyBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsReadOnlyBuffer); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::AsShortBuffer() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jAsShortBuffer); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Compact() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jCompact); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -int32_t ByteBuffer::CompareTo(jobject a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jCompareTo, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int32_t ByteBuffer::CompareTo1(jobject a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jCompareTo1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jobject ByteBuffer::Duplicate() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jDuplicate); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -bool ByteBuffer::Equals(jobject a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - bool temp = env->CallBooleanMethod(wrapped_obj, jEquals, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int8_t ByteBuffer::Get() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int8_t temp = env->CallByteMethod(wrapped_obj, jGet); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int8_t ByteBuffer::Get1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int8_t temp = env->CallByteMethod(wrapped_obj, jGet1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jobject ByteBuffer::Get1(jbyteArray a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jGet10, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Get1(jbyteArray a0, int32_t a1, int32_t a2) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[3]; - args[0].l = a0; - args[1].i = a1; - args[2].i = a2; - - jobject temp = env->CallObjectMethodA(wrapped_obj, jGet11, args); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -uint16_t ByteBuffer::GetChar() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - uint16_t temp = env->CallCharMethod(wrapped_obj, jGetChar); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -uint16_t ByteBuffer::GetChar1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - uint16_t temp = env->CallCharMethod(wrapped_obj, jGetChar1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jdouble ByteBuffer::GetDouble() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jdouble temp = env->CallDoubleMethod(wrapped_obj, jGetDouble); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jdouble ByteBuffer::GetDouble1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jdouble temp = env->CallDoubleMethod(wrapped_obj, jGetDouble1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jfloat ByteBuffer::GetFloat() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jfloat temp = env->CallFloatMethod(wrapped_obj, jGetFloat); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jfloat ByteBuffer::GetFloat1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jfloat temp = env->CallFloatMethod(wrapped_obj, jGetFloat1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int32_t ByteBuffer::GetInt() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jGetInt); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int32_t ByteBuffer::GetInt1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jGetInt1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int64_t ByteBuffer::GetLong() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int64_t temp = env->CallLongMethod(wrapped_obj, jGetLong); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int64_t ByteBuffer::GetLong1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int64_t temp = env->CallLongMethod(wrapped_obj, jGetLong1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int16_t ByteBuffer::GetShort() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int16_t temp = env->CallShortMethod(wrapped_obj, jGetShort); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int16_t ByteBuffer::GetShort1(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int16_t temp = env->CallShortMethod(wrapped_obj, jGetShort1, a0); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -bool ByteBuffer::HasArray() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - bool temp = env->CallBooleanMethod(wrapped_obj, jHasArray); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -int32_t ByteBuffer::HashCode() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - int32_t temp = env->CallIntMethod(wrapped_obj, jHashCode); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -bool ByteBuffer::IsDirect() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - bool temp = env->CallBooleanMethod(wrapped_obj, jIsDirect); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); - return temp; -} - -jobject ByteBuffer::Order() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jOrder); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Order1(jobject a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jOrder1, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Put(int8_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPut, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Put1(int32_t a0, int8_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPut1, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Put1(jobject a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPut12, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Put1(jbyteArray a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPut13, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Put1(jbyteArray a0, int32_t a1, int32_t a2) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[3]; - args[0].l = a0; - args[1].i = a1; - args[2].i = a2; - - jobject temp = env->CallObjectMethodA(wrapped_obj, jPut14, args); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutChar(uint16_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutChar, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutChar1(int32_t a0, uint16_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutChar1, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutDouble(jdouble a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutDouble, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutDouble1(int32_t a0, jdouble a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutDouble1, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutFloat(jfloat a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutFloat, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutFloat1(int32_t a0, jfloat a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutFloat1, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutInt(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutInt, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutInt1(int32_t a0, int32_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutInt1, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutLong(int32_t a0, int64_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutLong, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutLong1(int64_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutLong1, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutShort(int32_t a0, int16_t a1) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutShort, a0, a1); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::PutShort1(int16_t a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jPutShort1, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Slice() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jSlice); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jstring ByteBuffer::ToString() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(1) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallObjectMethod(wrapped_obj, jToString); - AndroidBridge::HandleUncaughtException(env); - jstring ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Wrap1(jbyteArray a0) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jobject temp = env->CallStaticObjectMethod(mByteBufferClass, jWrap, a0); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -jobject ByteBuffer::Wrap2(jbyteArray a0, int32_t a1, int32_t a2) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(2) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[3]; - args[0].l = a0; - args[1].i = a1; - args[2].i = a2; - - jobject temp = env->CallStaticObjectMethodA(mByteBufferClass, jWrap1, args); - AndroidBridge::HandleUncaughtException(env); - jobject ret = static_cast(env->PopLocalFrame(temp)); - return ret; -} - -bool ByteBuffer::getBigEndian() { - JNIEnv *env = GetJNIForThread(); - return env->GetBooleanField(wrapped_obj, jBigEndian); -} - -void ByteBuffer::setBigEndian(bool a0) { - JNIEnv *env = GetJNIForThread(); - env->SetBooleanField(wrapped_obj, jBigEndian, a0); -} - -jbyteArray ByteBuffer::getHb() { - JNIEnv *env = GetJNIForThread(); - return static_cast(env->GetObjectField(wrapped_obj, jHb)); -} - -bool ByteBuffer::getIsReadOnly() { - JNIEnv *env = GetJNIForThread(); - return env->GetBooleanField(wrapped_obj, jIsReadOnly); -} - -void ByteBuffer::setIsReadOnly(bool a0) { - JNIEnv *env = GetJNIForThread(); - env->SetBooleanField(wrapped_obj, jIsReadOnly, a0); -} - -bool ByteBuffer::getNativeByteOrder() { - JNIEnv *env = GetJNIForThread(); - return env->GetBooleanField(wrapped_obj, jNativeByteOrder); -} - -void ByteBuffer::setNativeByteOrder(bool a0) { - JNIEnv *env = GetJNIForThread(); - env->SetBooleanField(wrapped_obj, jNativeByteOrder, a0); -} - -int32_t ByteBuffer::getOffset() { - JNIEnv *env = GetJNIForThread(); - return env->GetIntField(wrapped_obj, jOffset); -} - -jclass BufferInfo::mBufferInfoClass = 0; -jmethodID BufferInfo::jBufferInfo = 0; -jmethodID BufferInfo::jSet = 0; -jfieldID BufferInfo::jFlags = 0; -jfieldID BufferInfo::jOffset = 0; -jfieldID BufferInfo::jPresentationTimeUs = 0; -jfieldID BufferInfo::jSize = 0; -void BufferInfo::InitStubs(JNIEnv *jEnv) { - initInit(); - - mBufferInfoClass = getClassGlobalRef("android/media/MediaCodec$BufferInfo"); - jBufferInfo = getMethod("", "()V"); - jSet = getMethod("set", "(IIJI)V"); - jFlags = getField("flags", "I"); - jOffset = getField("offset", "I"); - jPresentationTimeUs = getField("presentationTimeUs", "J"); - jSize = getField("size", "I"); -} - -BufferInfo* BufferInfo::Wrap(jobject obj) { - JNIEnv *env = GetJNIForThread(); - BufferInfo* ret = new BufferInfo(obj, env); - env->DeleteLocalRef(obj); - return ret; -} - -BufferInfo::BufferInfo() { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - Init(env->NewObject(mBufferInfoClass, jBufferInfo), env); - env->PopLocalFrame(nullptr); -} - -void BufferInfo::Set(int32_t a0, int32_t a1, int64_t a2, int32_t a3) { - JNIEnv *env = GetJNIForThread(); - if (env->PushLocalFrame(0) != 0) { - AndroidBridge::HandleUncaughtException(env); - MOZ_CRASH("Exception should have caused crash."); - } - - jvalue args[4]; - args[0].i = a0; - args[1].i = a1; - args[2].j = a2; - args[3].i = a3; - - env->CallVoidMethodA(wrapped_obj, jSet, args); - AndroidBridge::HandleUncaughtException(env); - env->PopLocalFrame(nullptr); -} - -int32_t BufferInfo::getFlags() { - JNIEnv *env = GetJNIForThread(); - return env->GetIntField(wrapped_obj, jFlags); -} - -void BufferInfo::setFlags(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - env->SetIntField(wrapped_obj, jFlags, a0); -} - -int32_t BufferInfo::getOffset() { - JNIEnv *env = GetJNIForThread(); - return env->GetIntField(wrapped_obj, jOffset); -} - -void BufferInfo::setOffset(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - env->SetIntField(wrapped_obj, jOffset, a0); -} - -int64_t BufferInfo::getPresentationTimeUs() { - JNIEnv *env = GetJNIForThread(); - return env->GetLongField(wrapped_obj, jPresentationTimeUs); -} - -void BufferInfo::setPresentationTimeUs(int64_t a0) { - JNIEnv *env = GetJNIForThread(); - env->SetLongField(wrapped_obj, jPresentationTimeUs, a0); -} - -int32_t BufferInfo::getSize() { - JNIEnv *env = GetJNIForThread(); - return env->GetIntField(wrapped_obj, jSize); -} - -void BufferInfo::setSize(int32_t a0) { - JNIEnv *env = GetJNIForThread(); - env->SetIntField(wrapped_obj, jSize, a0); -} - -void InitSDKStubs(JNIEnv *jEnv) { - MediaCodec::InitStubs(jEnv); - MediaFormat::InitStubs(jEnv); - ByteBuffer::InitStubs(jEnv); - BufferInfo::InitStubs(jEnv); -} -} /* android */ -} /* widget */ -} /* mozilla */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedSDKWrappers.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedSDKWrappers.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/GeneratedSDKWrappers.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/GeneratedSDKWrappers.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,335 +0,0 @@ -// GENERATED CODE - -// NOTE: This code has been doctored. The JarClassProcessor is still a work in progress, -// and so additions and deletions have been made to make this file valid. - -// Generated by the Java program at /build/jarClassProcessors at compile time from -// a given set of jars and a set of requested methods. To update, change the annotations -// on the corresponding Java methods and rerun the build. Manually updating this file -// will cause your build to fail. - -#ifndef GeneratedSDKWrappers_h__ -#define GeneratedSDKWrappers_h__ - -#include "nsXPCOMStrings.h" -#include "AndroidJavaWrappers.h" - -namespace mozilla { -namespace widget { -namespace android { - -#define MEDIACODEC_EXCEPTION_INDEX -255 - -void InitSDKStubs(JNIEnv *jEnv); - -class MediaCodec : public AutoGlobalWrappedJavaObject { -public: - static void InitStubs(JNIEnv *jEnv); - static MediaCodec* Wrap(jobject obj); - MediaCodec(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; - bool Configure(jobject a0, jobject a1, jobject a2, int32_t a3); - static jobject CreateByCodecName(const nsAString& a0); - static jobject CreateDecoderByType(const nsAString& a0); - static jobject CreateEncoderByType(const nsAString& a0); - int32_t DequeueInputBuffer(int64_t a0); - int32_t DequeueOutputBuffer(jobject a0, int64_t a1); - void Finalize(); - void Flush(); - jobjectArray GetInputBuffers(); - jobjectArray GetOutputBuffers(); - jobject GetOutputFormat(); - void QueueInputBuffer(int32_t a0, int32_t a1, int32_t a2, int64_t a3, int32_t a4); - void QueueSecureInputBuffer(int32_t a0, int32_t a1, jobject a2, int64_t a3, int32_t a4); - void Release(); - void ReleaseOutputBuffer(int32_t a0, bool a1); - void SetVideoScalingMode(int32_t a0); - bool Start(); - void Stop(); - static int32_t getBUFFER_FLAG_CODEC_CONFIG(); - static int32_t getBUFFER_FLAG_END_OF_STREAM(); - static int32_t getBUFFER_FLAG_SYNC_FRAME(); - static int32_t getCONFIGURE_FLAG_ENCODE(); - static int32_t getCRYPTO_MODE_AES_CTR(); - static int32_t getCRYPTO_MODE_UNENCRYPTED(); - static int32_t getINFO_OUTPUT_BUFFERS_CHANGED(); - static int32_t getINFO_OUTPUT_FORMAT_CHANGED(); - static int32_t getINFO_TRY_AGAIN_LATER(); - static int32_t getVIDEO_SCALING_MODE_SCALE_TO_FIT(); - static int32_t getVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING(); - MediaCodec() : AutoGlobalWrappedJavaObject() {}; -protected: - static jclass mMediaCodecClass; - static jmethodID jConfigure; - static jmethodID jCreateByCodecName; - static jmethodID jCreateDecoderByType; - static jmethodID jCreateEncoderByType; - static jmethodID jDequeueInputBuffer; - static jmethodID jDequeueOutputBuffer; - static jmethodID jFinalize; - static jmethodID jFlush; - static jmethodID jGetInputBuffers; - static jmethodID jGetOutputBuffers; - static jmethodID jGetOutputFormat; - static jmethodID jQueueInputBuffer; - static jmethodID jQueueSecureInputBuffer; - static jmethodID jRelease; - static jmethodID jReleaseOutputBuffer; - static jmethodID jSetVideoScalingMode; - static jmethodID jStart; - static jmethodID jStop; - static jfieldID jBUFFER_FLAG_CODEC_CONFIG; - static jfieldID jBUFFER_FLAG_END_OF_STREAM; - static jfieldID jBUFFER_FLAG_SYNC_FRAME; - static jfieldID jCONFIGURE_FLAG_ENCODE; - static jfieldID jCRYPTO_MODE_AES_CTR; - static jfieldID jCRYPTO_MODE_UNENCRYPTED; - static jfieldID jINFO_OUTPUT_BUFFERS_CHANGED; - static jfieldID jINFO_OUTPUT_FORMAT_CHANGED; - static jfieldID jINFO_TRY_AGAIN_LATER; - static jfieldID jVIDEO_SCALING_MODE_SCALE_TO_FIT; - static jfieldID jVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING; -}; - -class MediaFormat : public AutoGlobalWrappedJavaObject { -public: - static void InitStubs(JNIEnv *jEnv); - static MediaFormat* Wrap(jobject obj); - MediaFormat(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; - MediaFormat(); - bool ContainsKey(const nsAString& a0); - static jobject CreateAudioFormat(const nsAString& a0, int32_t a1, int32_t a2); - static jobject CreateVideoFormat(const nsAString& a0, int32_t a1, int32_t a2); - jobject GetByteBuffer(const nsAString& a0); - jfloat GetFloat(const nsAString& a0); - int32_t GetInteger(const nsAString& a0); - int64_t GetLong(const nsAString& a0); - jstring GetString(const nsAString& a0); - void SetByteBuffer(const nsAString& a0, jobject a1); - void SetFloat(const nsAString& a0, jfloat a1); - void SetInteger(const nsAString& a0, int32_t a1); - void SetLong(const nsAString& a0, int64_t a1); - void SetString(const nsAString& a0, const nsAString& a1); - jstring ToString(); - static jstring getKEY_AAC_PROFILE(); - static jstring getKEY_BIT_RATE(); - static jstring getKEY_CHANNEL_COUNT(); - static jstring getKEY_CHANNEL_MASK(); - static jstring getKEY_COLOR_FORMAT(); - static jstring getKEY_DURATION(); - static jstring getKEY_FLAC_COMPRESSION_LEVEL(); - static jstring getKEY_FRAME_RATE(); - static jstring getKEY_HEIGHT(); - static jstring getKEY_IS_ADTS(); - static jstring getKEY_I_FRAME_INTERVAL(); - static jstring getKEY_MAX_INPUT_SIZE(); - static jstring getKEY_MIME(); - static jstring getKEY_SAMPLE_RATE(); - static jstring getKEY_WIDTH(); -protected: - static jclass mMediaFormatClass; - static jmethodID jMediaFormat; - static jmethodID jContainsKey; - static jmethodID jCreateAudioFormat; - static jmethodID jCreateVideoFormat; - static jmethodID jGetByteBuffer; - static jmethodID jGetFloat; - static jmethodID jGetInteger; - static jmethodID jGetLong; - static jmethodID jGetString; - static jmethodID jSetByteBuffer; - static jmethodID jSetFloat; - static jmethodID jSetInteger; - static jmethodID jSetLong; - static jmethodID jSetString; - static jmethodID jToString; - static jfieldID jKEY_AAC_PROFILE; - static jfieldID jKEY_BIT_RATE; - static jfieldID jKEY_CHANNEL_COUNT; - static jfieldID jKEY_CHANNEL_MASK; - static jfieldID jKEY_COLOR_FORMAT; - static jfieldID jKEY_DURATION; - static jfieldID jKEY_FLAC_COMPRESSION_LEVEL; - static jfieldID jKEY_FRAME_RATE; - static jfieldID jKEY_HEIGHT; - static jfieldID jKEY_IS_ADTS; - static jfieldID jKEY_I_FRAME_INTERVAL; - static jfieldID jKEY_MAX_INPUT_SIZE; - static jfieldID jKEY_MIME; - static jfieldID jKEY_SAMPLE_RATE; - static jfieldID jKEY_WIDTH; -}; - -class ByteBuffer : public AutoGlobalWrappedJavaObject { -public: - static void InitStubs(JNIEnv *jEnv); - static ByteBuffer* Wrap(jobject obj); - ByteBuffer(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; - int8_t _get(int32_t a0); - void _put(int32_t a0, int8_t a1); - static jobject Allocate(int32_t a0); - static jobject AllocateDirect(int32_t a0); - jobject Array(); - jbyteArray Array1(); - int32_t ArrayOffset(); - jstring AsCharBuffer(); - jobject AsDoubleBuffer(); - jobject AsFloatBuffer(); - jobject AsIntBuffer(); - jobject AsLongBuffer(); - jobject AsReadOnlyBuffer(); - jobject AsShortBuffer(); - jobject Compact(); - int32_t CompareTo(jobject a0); - int32_t CompareTo1(jobject a0); - jobject Duplicate(); - bool Equals(jobject a0); - int8_t Get(); - int8_t Get1(int32_t a0); - jobject Get1(jbyteArray a0); - jobject Get1(jbyteArray a0, int32_t a1, int32_t a2); - uint16_t GetChar(); - uint16_t GetChar1(int32_t a0); - jdouble GetDouble(); - jdouble GetDouble1(int32_t a0); - jfloat GetFloat(); - jfloat GetFloat1(int32_t a0); - int32_t GetInt(); - int32_t GetInt1(int32_t a0); - int64_t GetLong(); - int64_t GetLong1(int32_t a0); - int16_t GetShort(); - int16_t GetShort1(int32_t a0); - bool HasArray(); - int32_t HashCode(); - bool IsDirect(); - jobject Order(); - jobject Order1(jobject a0); - jobject Put(int8_t a0); - jobject Put1(int32_t a0, int8_t a1); - jobject Put1(jobject a0); - jobject Put1(jbyteArray a0); - jobject Put1(jbyteArray a0, int32_t a1, int32_t a2); - jobject PutChar(uint16_t a0); - jobject PutChar1(int32_t a0, uint16_t a1); - jobject PutDouble(jdouble a0); - jobject PutDouble1(int32_t a0, jdouble a1); - jobject PutFloat(jfloat a0); - jobject PutFloat1(int32_t a0, jfloat a1); - jobject PutInt(int32_t a0); - jobject PutInt1(int32_t a0, int32_t a1); - jobject PutLong(int32_t a0, int64_t a1); - jobject PutLong1(int64_t a0); - jobject PutShort(int32_t a0, int16_t a1); - jobject PutShort1(int16_t a0); - jobject Slice(); - jstring ToString(); - static jobject Wrap1(jbyteArray a0); - static jobject Wrap2(jbyteArray a0, int32_t a1, int32_t a2); - bool getBigEndian(); - void setBigEndian(bool a0); - jbyteArray getHb(); - bool getIsReadOnly(); - void setIsReadOnly(bool a0); - bool getNativeByteOrder(); - void setNativeByteOrder(bool a0); - int32_t getOffset(); - ByteBuffer() : AutoGlobalWrappedJavaObject() {}; -protected: - static jclass mByteBufferClass; - static jmethodID j_get; - static jmethodID j_put; - static jmethodID jAllocate; - static jmethodID jAllocateDirect; - static jmethodID jArray; - static jmethodID jArray1; - static jmethodID jArrayOffset; - static jmethodID jAsCharBuffer; - static jmethodID jAsDoubleBuffer; - static jmethodID jAsFloatBuffer; - static jmethodID jAsIntBuffer; - static jmethodID jAsLongBuffer; - static jmethodID jAsReadOnlyBuffer; - static jmethodID jAsShortBuffer; - static jmethodID jCompact; - static jmethodID jCompareTo; - static jmethodID jCompareTo1; - static jmethodID jDuplicate; - static jmethodID jEquals; - static jmethodID jGet; - static jmethodID jGet1; - static jmethodID jGet10; - static jmethodID jGet11; - static jmethodID jGetChar; - static jmethodID jGetChar1; - static jmethodID jGetDouble; - static jmethodID jGetDouble1; - static jmethodID jGetFloat; - static jmethodID jGetFloat1; - static jmethodID jGetInt; - static jmethodID jGetInt1; - static jmethodID jGetLong; - static jmethodID jGetLong1; - static jmethodID jGetShort; - static jmethodID jGetShort1; - static jmethodID jHasArray; - static jmethodID jHashCode; - static jmethodID jIsDirect; - static jmethodID jOrder; - static jmethodID jOrder1; - static jmethodID jPut; - static jmethodID jPut1; - static jmethodID jPut12; - static jmethodID jPut13; - static jmethodID jPut14; - static jmethodID jPutChar; - static jmethodID jPutChar1; - static jmethodID jPutDouble; - static jmethodID jPutDouble1; - static jmethodID jPutFloat; - static jmethodID jPutFloat1; - static jmethodID jPutInt; - static jmethodID jPutInt1; - static jmethodID jPutLong; - static jmethodID jPutLong1; - static jmethodID jPutShort; - static jmethodID jPutShort1; - static jmethodID jSlice; - static jmethodID jToString; - static jmethodID jWrap; - static jmethodID jWrap1; - static jfieldID jBigEndian; - static jfieldID jHb; - static jfieldID jIsReadOnly; - static jfieldID jNativeByteOrder; - static jfieldID jOffset; -}; - -class BufferInfo : public AutoGlobalWrappedJavaObject { -public: - static void InitStubs(JNIEnv *jEnv); - static BufferInfo* Wrap(jobject obj); - BufferInfo(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {}; - BufferInfo(); - void Set(int32_t a0, int32_t a1, int64_t a2, int32_t a3); - int32_t getFlags(); - void setFlags(int32_t a0); - int32_t getOffset(); - void setOffset(int32_t a0); - int64_t getPresentationTimeUs(); - void setPresentationTimeUs(int64_t a0); - int32_t getSize(); - void setSize(int32_t a0); -protected: - static jclass mBufferInfoClass; - static jmethodID jBufferInfo; - static jmethodID jSet; - static jfieldID jFlags; - static jfieldID jOffset; - static jfieldID jPresentationTimeUs; - static jfieldID jSize; -}; - -} /* android */ -} /* widget */ -} /* mozilla */ -#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/moz.build 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/moz.build 2014-11-26 21:46:06.000000000 +0000 @@ -4,6 +4,10 @@ # 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/. +DIRS += [ + 'bindings', +] + XPIDL_SOURCES += [ 'nsIAndroidBridge.idl', ] @@ -15,7 +19,6 @@ 'AndroidJavaWrappers.h', 'AndroidJNIWrapper.h', 'GeneratedJNIWrappers.h', - 'GeneratedSDKWrappers.h', ] SOURCES += [ @@ -27,7 +30,6 @@ 'AndroidJNIWrapper.cpp', 'APZCCallbackHandler.cpp', 'GeneratedJNIWrappers.cpp', - 'GeneratedSDKWrappers.cpp', 'GfxInfo.cpp', 'NativeJSContainer.cpp', 'nsAndroidProtocolHandler.cpp', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/nsWindow.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/nsWindow.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/nsWindow.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/nsWindow.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -675,7 +675,8 @@ MOZ_ASSERT(!mIMEComposing); mIMEComposing = true; break; - case NS_COMPOSITION_END: + case NS_COMPOSITION_COMMIT_AS_IS: + case NS_COMPOSITION_COMMIT: MOZ_ASSERT(mIMEComposing); mIMEComposing = false; mIMEComposingStart = -1; @@ -692,7 +693,7 @@ } NS_IMETHODIMP -nsWindow::MakeFullScreen(bool aFullScreen) +nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) { mozilla::widget::android::GeckoAppShell::SetFullScreen(aFullScreen); return NS_OK; @@ -1718,15 +1719,11 @@ AutoIMEMask selMask(mIMEMaskSelectionUpdate); AutoIMEMask textMask(mIMEMaskTextUpdate); - WidgetCompositionEvent compositionChangeEvent(true, NS_COMPOSITION_CHANGE, + WidgetCompositionEvent compositionCommitEvent(true, + NS_COMPOSITION_COMMIT_AS_IS, this); - InitEvent(compositionChangeEvent, nullptr); - compositionChangeEvent.mData = mIMEComposingText; - DispatchEvent(&compositionChangeEvent); - - WidgetCompositionEvent compEndEvent(true, NS_COMPOSITION_END, this); - InitEvent(compEndEvent, nullptr); - DispatchEvent(&compEndEvent); + InitEvent(compositionCommitEvent, nullptr); + DispatchEvent(&compositionCommitEvent); } void @@ -1878,10 +1875,11 @@ // Don't end composition when composing text. if (ae->Action() != AndroidGeckoEvent::IME_COMPOSE_TEXT) { - WidgetCompositionEvent event(true, NS_COMPOSITION_END, this); - InitEvent(event, nullptr); - event.mData = ae->Characters(); - DispatchEvent(&event); + WidgetCompositionEvent compositionCommitEvent( + true, NS_COMPOSITION_COMMIT, this); + InitEvent(compositionCommitEvent, nullptr); + compositionCommitEvent.mData = ae->Characters(); + DispatchEvent(&compositionCommitEvent); } FlushIMEChanges(); @@ -2083,15 +2081,12 @@ if (mIMEComposing) { nsRefPtr kungFuDeathGrip(this); - WidgetCompositionEvent compositionChangeEvent( - true, NS_COMPOSITION_CHANGE, this); - InitEvent(compositionChangeEvent, nullptr); - DispatchEvent(&compositionChangeEvent); - - WidgetCompositionEvent compositionEndEvent( - true, NS_COMPOSITION_END, this); - InitEvent(compositionEndEvent, nullptr); - DispatchEvent(&compositionEndEvent); + WidgetCompositionEvent compositionCommitEvent( + true, NS_COMPOSITION_COMMIT, this); + InitEvent(compositionCommitEvent, nullptr); + // Dispatch it with empty mData value for canceling the + // composition + DispatchEvent(&compositionCommitEvent); } mozilla::widget::android::GeckoAppShell::NotifyIME(REQUEST_TO_CANCEL_COMPOSITION); @@ -2369,7 +2364,9 @@ return; } - gl::GLContext* gl = static_cast(aManager->GetCompositor())->gl(); + CompositorOGL *compositor = static_cast(aManager->GetCompositor()); + compositor->ResetProgram(); + gl::GLContext* gl = compositor->gl(); bool scissorEnabled = gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST); GLint scissorRect[4]; gl->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorRect); @@ -2398,7 +2395,9 @@ mozilla::widget::android::GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient(); - gl::GLContext* gl = static_cast(aManager->GetCompositor())->gl(); + CompositorOGL *compositor = static_cast(aManager->GetCompositor()); + compositor->ResetProgram(); + gl::GLContext* gl = compositor->gl(); bool scissorEnabled = gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST); GLint scissorRect[4]; gl->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorRect); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/nsWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/nsWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/android/nsWindow.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/android/nsWindow.h 2014-11-26 21:46:06.000000000 +0000 @@ -104,7 +104,7 @@ NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus); nsEventStatus DispatchEvent(mozilla::WidgetGUIEvent* aEvent); - NS_IMETHOD MakeFullScreen(bool aFullScreen); + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr); NS_IMETHOD SetWindowClass(const nsAString& xulWinType); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/BasicEvents.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/BasicEvents.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/BasicEvents.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/BasicEvents.h 2014-11-26 21:46:06.000000000 +0000 @@ -176,6 +176,9 @@ // composition events #define NS_COMPOSITION_EVENT_START 2200 #define NS_COMPOSITION_START (NS_COMPOSITION_EVENT_START) +// NS_COMPOSITION_END is the message for DOM compositionend event. +// This event should NOT be dispatched from widget if NS_COMPOSITION_COMMIT +// is available. #define NS_COMPOSITION_END (NS_COMPOSITION_EVENT_START + 1) // NS_COMPOSITION_UPDATE is the message for DOM compositionupdate event. // This event should NOT be dispatched from widget since it will be dispatched @@ -187,6 +190,19 @@ // composition string isn't changed but the ranges are changed. This causes // a DOM "text" event which is a non-standard DOM event. #define NS_COMPOSITION_CHANGE (NS_COMPOSITION_EVENT_START + 3) +// NS_COMPOSITION_COMMIT_AS_IS is the message for representing a commit of +// composition string. TextComposition will commit composition with the +// last data. TextComposition will dispatch this event to the DOM tree as +// NS_COMPOSITION_CHANGE without clause information. After that, +// NS_COMPOSITION_END will be dispatched automatically. +// Its mData and mRanges should be empty and nullptr. +#define NS_COMPOSITION_COMMIT_AS_IS (NS_COMPOSITION_EVENT_START + 4) +// NS_COMPOSITION_COMMIT is the message for representing a commit of +// composition string with its mData value. TextComposition will dispatch this +// event to the DOM tree as NS_COMPOSITION_CHANGE without clause information. +// After that, NS_COMPOSITION_END will be dispatched automatically. +// Its mRanges should be nullptr. +#define NS_COMPOSITION_COMMIT (NS_COMPOSITION_EVENT_START + 5) // UI events #define NS_UI_EVENT_START 2500 diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/GfxInfo.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/GfxInfo.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/GfxInfo.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/GfxInfo.h 2014-11-26 21:46:06.000000000 +0000 @@ -9,6 +9,7 @@ #define __mozilla_widget_GfxInfo_h__ #include "GfxInfoBase.h" +#include "nsIGfxInfo2.h" #include "nsString.h" @@ -50,10 +51,11 @@ virtual nsresult Init(); -#ifdef DEBUG NS_DECL_ISUPPORTS_INHERITED +#ifdef DEBUG NS_DECL_NSIGFXINFODEBUG #endif + NS_DECL_NSIGFXINFO2 virtual uint32_t OperatingSystemVersion() MOZ_OVERRIDE { return mOSXVersion; } @@ -71,6 +73,7 @@ private: void GetDeviceInfo(); + void GetSelectedCityInfo(); void AddCrashReportAnnotations(); nsString mAdapterRAMString; @@ -82,6 +85,8 @@ nsString mAdapterVendorID; nsString mAdapterDeviceID; + nsString mCountryCode; + uint32_t mOSXVersion; }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/GfxInfo.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/GfxInfo.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/GfxInfo.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/GfxInfo.mm 2014-11-26 21:46:06.000000000 +0000 @@ -34,7 +34,9 @@ using namespace mozilla::widget; #ifdef DEBUG -NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) +NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfo2, nsIGfxInfoDebug) +#else +NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfo2) #endif GfxInfo::GfxInfo() @@ -96,6 +98,20 @@ } } +void +GfxInfo::GetSelectedCityInfo() +{ + NSDictionary* selected_city = + [[NSUserDefaults standardUserDefaults] + objectForKey:@"com.apple.preferences.timezone.selected_city"]; + NSString *countryCode = (NSString *) + [selected_city objectForKey:@"CountryCode"]; + const char *countryCodeUTF8 = [countryCode UTF8String]; + if (countryCodeUTF8) { + AppendUTF8toUTF16(countryCodeUTF8, mCountryCode); + } +} + nsresult GfxInfo::Init() { @@ -107,6 +123,8 @@ GetDeviceInfo(); + GetSelectedCityInfo(); + AddCrashReportAnnotations(); mOSXVersion = nsCocoaFeatures::OSXVersion(); @@ -266,6 +284,15 @@ return NS_ERROR_FAILURE; } +/* interface nsIGfxInfo2 */ +/* readonly attribute DOMString countryCode; */ +NS_IMETHODIMP +GfxInfo::GetCountryCode(nsAString & aCountryCode) +{ + aCountryCode = mCountryCode; + return NS_OK; +} + void GfxInfo::AddCrashReportAnnotations() { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/NativeKeyBindings.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/NativeKeyBindings.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/NativeKeyBindings.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/NativeKeyBindings.mm 2014-11-26 21:46:06.000000000 +0000 @@ -282,7 +282,7 @@ PR_LOG(gNativeKeyBindingsLog, PR_LOG_ALWAYS, ("%p NativeKeyBindings::KeyPress, command=%s", - this, geckoCommand)); + this, WidgetKeyboardEvent::GetCommandStr(geckoCommand))); // Execute the Gecko command aCallback(geckoCommand, aCallbackData); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsAppShell.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsAppShell.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsAppShell.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsAppShell.h 2014-11-26 21:46:06.000000000 +0000 @@ -5,7 +5,7 @@ /* * Runs the main native Cocoa run loop, interrupting it as needed to process - * Gecko events. + * Gecko events. */ #ifndef nsAppShell_h_ @@ -30,7 +30,7 @@ { public: NS_IMETHOD ResumeNative(void); - + nsAppShell(); nsresult Init(); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsAppShell.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsAppShell.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsAppShell.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsAppShell.mm 2014-11-26 21:46:06.000000000 +0000 @@ -87,7 +87,7 @@ } return NS_OK; } -}; +}; // MacWakeLockListener // defined in nsCocoaWindow.mm extern int32_t gXULModalLevel; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsChildView.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsChildView.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsChildView.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsChildView.h 2014-11-26 21:46:06.000000000 +0000 @@ -504,6 +504,13 @@ const mozilla::WidgetKeyboardEvent& aEvent, DoCommandCallback aCallback, void* aCallbackData) MOZ_OVERRIDE; + bool ExecuteNativeKeyBindingRemapped( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + DoCommandCallback aCallback, + void* aCallbackData, + uint32_t aGeckoKeyCode, + uint32_t aCocoaKeyCode); virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE; NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsChildView.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsChildView.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsChildView.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsChildView.mm 2014-11-26 21:46:06.000000000 +0000 @@ -225,6 +225,10 @@ - (CGSRegionObj)_regionForOpaqueDescendants:(NSRect)aRect forMove:(BOOL)aForMove forUnderTitlebar:(BOOL)aForUnderTitlebar; @end +@interface NSWindow(NSWindowShouldZoomOnDoubleClick) ++ (BOOL)_shouldZoomOnDoubleClick; // present on 10.7 and above +@end + // Starting with 10.7 the bottom corners of all windows are rounded. // Unfortunately, the standard rounding that OS X applies to OpenGL views // does not use anti-aliasing and looks very crude. Since we want a smooth, @@ -375,6 +379,10 @@ { return mProjMatrix; } + virtual void ActivateProgram(ShaderProgramOGL *aProg) MOZ_OVERRIDE + { + mGLContext->fUseProgram(aProg->GetProgram()); + } virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, const gfx::Rect& aLayerRect, const gfx::Rect& aTextureRect) MOZ_OVERRIDE; @@ -2030,12 +2038,96 @@ return mTextInputHandler->AttachNativeKeyEvent(aEvent); } +bool +nsChildView::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + DoCommandCallback aCallback, + void* aCallbackData, + uint32_t aGeckoKeyCode, + uint32_t aCocoaKeyCode) +{ + NSEvent *originalEvent = reinterpret_cast(aEvent.mNativeKeyEvent); + + WidgetKeyboardEvent modifiedEvent(aEvent); + modifiedEvent.keyCode = aGeckoKeyCode; + + unichar ch = nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(aGeckoKeyCode); + NSString *chars = + [[[NSString alloc] initWithCharacters:&ch length:1] autorelease]; + + modifiedEvent.mNativeKeyEvent = + [NSEvent keyEventWithType:[originalEvent type] + location:[originalEvent locationInWindow] + modifierFlags:[originalEvent modifierFlags] + timestamp:[originalEvent timestamp] + windowNumber:[originalEvent windowNumber] + context:[originalEvent context] + characters:chars + charactersIgnoringModifiers:chars + isARepeat:[originalEvent isARepeat] + keyCode:aCocoaKeyCode]; + + NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); + return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData); +} + NS_IMETHODIMP_(bool) nsChildView::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent, DoCommandCallback aCallback, void* aCallbackData) { + // If the key is a cursor-movement arrow, and the current selection has + // vertical writing-mode, we'll remap so that the movement command + // generated (in terms of characters/lines) will be appropriate for + // the physical direction of the arrow. + if (aEvent.keyCode >= nsIDOMKeyEvent::DOM_VK_LEFT && + aEvent.keyCode <= nsIDOMKeyEvent::DOM_VK_DOWN) { + WidgetQueryContentEvent query(true, NS_QUERY_SELECTED_TEXT, this); + DispatchWindowEvent(query); + + if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) { + uint32_t geckoKey = 0; + uint32_t cocoaKey = 0; + + switch (aEvent.keyCode) { + case nsIDOMKeyEvent::DOM_VK_LEFT: + if (query.mReply.mWritingMode.IsVerticalLR()) { + geckoKey = nsIDOMKeyEvent::DOM_VK_UP; + cocoaKey = kVK_UpArrow; + } else { + geckoKey = nsIDOMKeyEvent::DOM_VK_DOWN; + cocoaKey = kVK_DownArrow; + } + break; + + case nsIDOMKeyEvent::DOM_VK_RIGHT: + if (query.mReply.mWritingMode.IsVerticalLR()) { + geckoKey = nsIDOMKeyEvent::DOM_VK_DOWN; + cocoaKey = kVK_DownArrow; + } else { + geckoKey = nsIDOMKeyEvent::DOM_VK_UP; + cocoaKey = kVK_UpArrow; + } + break; + + case nsIDOMKeyEvent::DOM_VK_UP: + geckoKey = nsIDOMKeyEvent::DOM_VK_LEFT; + cocoaKey = kVK_LeftArrow; + break; + + case nsIDOMKeyEvent::DOM_VK_DOWN: + geckoKey = nsIDOMKeyEvent::DOM_VK_RIGHT; + cocoaKey = kVK_RightArrow; + break; + } + + return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback, + aCallbackData, + geckoKey, cocoaKey); + } + } + NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); return keyBindings->Execute(aEvent, aCallback, aCallbackData); } @@ -2956,7 +3048,7 @@ aManager->gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, mTexture); - program->Activate(); + aManager->ActivateProgram(program); program->SetProjectionMatrix(aManager->GetProjMatrix()); program->SetLayerTransform(Matrix4x4(aTransform).PostTranslate(aLocation.x, aLocation.y, 0)); program->SetTextureTransform(gfx::Matrix4x4()); @@ -4884,13 +4976,15 @@ LayoutDeviceIntPoint pos = geckoEvent.refPoint; if (!defaultPrevented && [theEvent clickCount] == 2 && mGeckoChild->GetDraggableRegion().Contains(pos.x, pos.y) && - [self shouldMinimizeOnTitlebarDoubleClick] && [[self window] isKindOfClass:[ToolbarWindow class]] && (locationInTitlebar < [(ToolbarWindow*)[self window] titlebarHeight] || locationInTitlebar < [(ToolbarWindow*)[self window] unifiedToolbarHeight])) { - - NSButton *minimizeButton = [[self window] standardWindowButton:NSWindowMiniaturizeButton]; - [minimizeButton performClick:self]; + if ([self shouldZoomOnDoubleClick]) { + [[self window] performZoom:nil]; + } else if ([self shouldMinimizeOnTitlebarDoubleClick]) { + NSButton *minimizeButton = [[self window] standardWindowButton:NSWindowMiniaturizeButton]; + [minimizeButton performClick:self]; + } } // If our mouse-up event's location is over some other object (as might @@ -5631,6 +5725,14 @@ return mTextInputHandler->HasMarkedText(); } +- (BOOL)shouldZoomOnDoubleClick +{ + if ([NSWindow respondsToSelector:@selector(_shouldZoomOnDoubleClick)]) { + return [NSWindow _shouldZoomOnDoubleClick]; + } + return nsCocoaFeatures::OnYosemiteOrLater(); +} + - (BOOL)shouldMinimizeOnTitlebarDoubleClick { NSString *MDAppleMiniaturizeOnDoubleClickKey = diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaFeatures.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaFeatures.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaFeatures.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaFeatures.h 2014-11-26 21:46:06.000000000 +0000 @@ -21,12 +21,11 @@ static bool SupportCoreAnimationPlugins(); static bool AccelerateByDefault(); + static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0); + private: static void InitializeVersionNumbers(); static int32_t mOSXVersion; - static int32_t mOSXVersionMajor; - static int32_t mOSXVersionMinor; - static int32_t mOSXVersionBugFix; }; #endif // nsCocoaFeatures_h_ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaFeatures.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaFeatures.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaFeatures.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaFeatures.mm 2014-11-26 21:46:06.000000000 +0000 @@ -3,7 +3,18 @@ * 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/. */ +// This file makes some assumptions about the versions of OS X. +// Instead of making it work major version 11 right now, +// we will wait until that happens and worry about it then. +// There are MOZ_ASSERTs to remind us to do that. +// We are assuming that the minor version is less than 16. +// There are MOZ_ASSERTs for that as well. + +// The formula for the version integer based on OS X version 10.minor.bugfix is +// 0x1000 + (minor << 4) + bugifix. See AssembleVersion() below. + #define MAC_OS_X_VERSION_MASK 0x0000FFFF +#define MAC_OS_X_VERSION_10_0_HEX 0x00001000 #define MAC_OS_X_VERSION_10_6_HEX 0x00001060 #define MAC_OS_X_VERSION_10_7_HEX 0x00001070 #define MAC_OS_X_VERSION_10_8_HEX 0x00001080 @@ -18,9 +29,31 @@ #import int32_t nsCocoaFeatures::mOSXVersion = 0; -int32_t nsCocoaFeatures::mOSXVersionMajor = 0; -int32_t nsCocoaFeatures::mOSXVersionMinor = 0; -int32_t nsCocoaFeatures::mOSXVersionBugFix = 0; + +inline int32_t AssembleVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) +{ + MOZ_ASSERT(aMajor == 10); + return MAC_OS_X_VERSION_10_0_HEX + (aMinor << 4) + aBugFix; +} + +inline int32_t ExtractMajorVersion(int32_t aVersion) +{ + MOZ_ASSERT((aVersion & MAC_OS_X_VERSION_MASK) == aVersion); + MOZ_ASSERT((aVersion & MAC_OS_X_VERSION_10_0_HEX) == MAC_OS_X_VERSION_10_0_HEX); + return 10; +} + +inline int32_t ExtractMinorVersion(int32_t aVersion) +{ + MOZ_ASSERT((aVersion & MAC_OS_X_VERSION_MASK) == aVersion); + return (aVersion & 0xF0) >> 4; +} + +inline int32_t ExtractBugFixVersion(int32_t aVersion) +{ + MOZ_ASSERT((aVersion & MAC_OS_X_VERSION_MASK) == aVersion); + return aVersion & 0x0F; +} static int intAtStringIndex(NSArray *array, int index) { @@ -46,6 +79,30 @@ } } +static int32_t GetFullVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) +{ + int32_t osxVersion; + if (aMajor < 10) { + aMajor = 10; + NS_ERROR("Couldn't determine OS X version, assuming 10.6"); + osxVersion = MAC_OS_X_VERSION_10_6_HEX; + } else if (aMinor < 6) { + aMinor = 6; + NS_ERROR("OS X version too old, assuming 10.6"); + osxVersion = MAC_OS_X_VERSION_10_6_HEX; + } else { + MOZ_ASSERT(aMajor == 10); + MOZ_ASSERT(aMinor < 16); + MOZ_ASSERT(aBugFix >= 0); + MOZ_ASSERT(aBugFix < 16); + osxVersion = AssembleVersion(aMajor, aMinor, aBugFix); + } + MOZ_ASSERT(aMajor == ExtractMajorVersion(osxVersion)); + MOZ_ASSERT(aMinor == ExtractMinorVersion(osxVersion)); + MOZ_ASSERT(aBugFix == ExtractBugFixVersion(osxVersion)); + return osxVersion; +} + /*static*/ void nsCocoaFeatures::InitializeVersionNumbers() { @@ -57,25 +114,7 @@ int major, minor, bugfix; GetSystemVersion(major, minor, bugfix); - - mOSXVersionMajor = major; - mOSXVersionMinor = minor; - mOSXVersionBugFix = bugfix; - - if (major < 10) { - NS_ERROR("Couldn't determine OS X version, assuming 10.6"); - mOSXVersion = MAC_OS_X_VERSION_10_6_HEX; - mOSXVersionMajor = 10; - mOSXVersionMinor = 6; - mOSXVersionBugFix = 0; - } else if (minor < 6) { - NS_ERROR("OS X version too old, assuming 10.6"); - mOSXVersion = MAC_OS_X_VERSION_10_6_HEX; - mOSXVersionMinor = 6; - mOSXVersionBugFix = 0; - } else { - mOSXVersion = 0x1000 + (minor << 4); - } + mOSXVersion = GetFullVersion(major, minor, bugfix); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -83,7 +122,10 @@ /* static */ int32_t nsCocoaFeatures::OSXVersion() { + // Don't let this be called while we're first setting the value... + MOZ_ASSERT((mOSXVersion & MAC_OS_X_VERSION_MASK) >= 0); if (!mOSXVersion) { + mOSXVersion = -1; InitializeVersionNumbers(); } return mOSXVersion; @@ -92,28 +134,20 @@ /* static */ int32_t nsCocoaFeatures::OSXVersionMajor() { - if (!mOSXVersion) { - InitializeVersionNumbers(); - } - return mOSXVersionMajor; + MOZ_ASSERT((OSXVersion() & MAC_OS_X_VERSION_10_0_HEX) == MAC_OS_X_VERSION_10_0_HEX); + return 10; } /* static */ int32_t nsCocoaFeatures::OSXVersionMinor() { - if (!mOSXVersion) { - InitializeVersionNumbers(); - } - return mOSXVersionMinor; + return ExtractMinorVersion(OSXVersion()); } /* static */ int32_t nsCocoaFeatures::OSXVersionBugFix() { - if (!mOSXVersion) { - InitializeVersionNumbers(); - } - return mOSXVersionBugFix; + return ExtractBugFixVersion(OSXVersion()); } /* static */ bool @@ -151,8 +185,11 @@ /* static */ bool nsCocoaFeatures::AccelerateByDefault() { - return !(OSXVersionMajor() == 10 && - OSXVersionMinor() == 6 && - OSXVersionBugFix() <= 2); + return IsAtLeastVersion(10, 6, 3); } +/* static */ bool +nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) +{ + return OSXVersion() >= GetFullVersion(aMajor, aMinor, aBugFix); +} diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaWindow.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaWindow.h 2014-11-26 21:46:06.000000000 +0000 @@ -275,7 +275,7 @@ NS_IMETHOD SetSizeMode(int32_t aMode); NS_IMETHOD HideWindowChrome(bool aShouldHide); void EnteredFullScreen(bool aFullScreen); - NS_IMETHOD MakeFullScreen(bool aFullScreen); + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr); NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint); NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint); NS_IMETHOD GetClientBounds(nsIntRect &aRect); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaWindow.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaWindow.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsCocoaWindow.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsCocoaWindow.mm 2014-11-26 21:46:06.000000000 +0000 @@ -1280,7 +1280,7 @@ DispatchSizeModeEvent(); } -NS_METHOD nsCocoaWindow::MakeFullScreen(bool aFullScreen) +NS_METHOD nsCocoaWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; @@ -2579,6 +2579,13 @@ - (void)_setNeedsDisplayInRect:(NSRect)aRect; @end +// This method is on NSThemeFrame starting with 10.10, but since NSThemeFrame +// is not a public class, we declare the method on NSView instead. We only have +// this declaration in order to avoid compiler warnings. +@interface NSView(PrivateAddKnownSubviewMethod) + - (void)_addKnownSubview:(NSView*)aView positioned:(NSWindowOrderingMode)place relativeTo:(NSView*)otherView; +@end + @interface BaseWindow(Private) - (void)removeTrackingArea; - (void)cursorUpdated:(NSEvent*)aEvent; @@ -2947,7 +2954,13 @@ // to be under the window buttons. NSView* frameView = [aView superview]; [aView removeFromSuperview]; - [frameView addSubview:aView positioned:NSWindowBelow relativeTo:nil]; + if ([frameView respondsToSelector:@selector(_addKnownSubview:positioned:relativeTo:)]) { + // 10.10 prints a warning when we call addSubview on the frame view, so we + // silence the warning by calling a private method instead. + [frameView _addKnownSubview:aView positioned:NSWindowBelow relativeTo:nil]; + } else { + [frameView addSubview:aView positioned:NSWindowBelow relativeTo:nil]; + } } - (NSArray*)titlebarControls diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsMenuItemIconX.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsMenuItemIconX.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsMenuItemIconX.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsMenuItemIconX.h 2014-11-26 21:46:06.000000000 +0000 @@ -52,7 +52,7 @@ void Destroy(); protected: - nsresult OnStopFrame(imgIRequest* aRequest); + nsresult OnFrameComplete(imgIRequest* aRequest); nsCOMPtr mContent; nsRefPtr mIconRequest; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsMenuItemIconX.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsMenuItemIconX.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsMenuItemIconX.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsMenuItemIconX.mm 2014-11-26 21:46:06.000000000 +0000 @@ -306,7 +306,9 @@ [mNativeMenuItem setImage:sPlaceholderIconImage]; } - nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this, + nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, + mozilla::net::RP_Default, + nullptr, loadGroup, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, nsIContentPolicy::TYPE_IMAGE, EmptyString(), getter_AddRefs(mIconRequest)); @@ -325,10 +327,12 @@ // NS_IMETHODIMP -nsMenuItemIconX::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) +nsMenuItemIconX::Notify(imgIRequest* aRequest, + int32_t aType, + const nsIntRect* aData) { if (aType == imgINotificationObserver::FRAME_COMPLETE) { - return OnStopFrame(aRequest); + return OnFrameComplete(aRequest); } if (aType == imgINotificationObserver::DECODE_COMPLETE) { @@ -342,7 +346,7 @@ } nsresult -nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest) +nsMenuItemIconX::OnFrameComplete(imgIRequest* aRequest) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsNativeThemeCocoa.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsNativeThemeCocoa.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/nsNativeThemeCocoa.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/nsNativeThemeCocoa.mm 2014-11-26 21:46:06.000000000 +0000 @@ -1095,10 +1095,7 @@ // On 10.6 and at least on 10.7.0, Apple doesn’t seem to have implemented all // keys and values used on 10.7.5 and later. We can however draw menu icons // on earlier OS versions by using different keys/values. - BOOL otherKeysAndValues = !nsCocoaFeatures::OnLionOrLater() || - (nsCocoaFeatures::OSXVersionMajor() == 10 && - nsCocoaFeatures::OSXVersionMinor() == 7 && - nsCocoaFeatures::OSXVersionBugFix() < 5); + BOOL otherKeysAndValues = !nsCocoaFeatures::IsAtLeastVersion(10,7,5); // 2 states combined with 2 different backgroundTypeKeys on earlier versions. NSString* state = isDisabled ? @"disabled" : @@ -2292,7 +2289,7 @@ IsHiDPIContext(nsPresContext* aContext) { return nsPresContext::AppUnitsPerCSSPixel() >= - 2 * aContext->DeviceContext()->UnscaledAppUnitsPerDevPixel(); + 2 * aContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); } NS_IMETHODIMP diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/OSXNotificationCenter.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/OSXNotificationCenter.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/OSXNotificationCenter.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/OSXNotificationCenter.mm 2014-11-26 21:46:06.000000000 +0000 @@ -243,7 +243,9 @@ nsCOMPtr imageUri; NS_NewURI(getter_AddRefs(imageUri), aImageUrl); if (imageUri) { - nsresult rv = il->LoadImage(imageUri, nullptr, nullptr, aPrincipal, nullptr, + nsresult rv = il->LoadImage(imageUri, nullptr, nullptr, + mozilla::net::RP_Default, + aPrincipal, nullptr, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, nsIContentPolicy::TYPE_IMAGE, EmptyString(), getter_AddRefs(osxni->mIconRequest)); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/TextInputHandler.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/TextInputHandler.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/TextInputHandler.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/TextInputHandler.h 2014-11-26 21:46:06.000000000 +0000 @@ -853,13 +853,19 @@ * @param aAttrString An NSAttributedString instance which indicates * current composition string. * @param aSelectedRange Current selected range (or caret position). - * @param aDoCommit TRUE if the composition string should be - * committed. Otherwise, FALSE. */ bool DispatchCompositionChangeEvent(const nsString& aText, NSAttributedString* aAttrString, - NSRange& aSelectedRange, - bool aDoCommit); + NSRange& aSelectedRange); + + /** + * DispatchCompositionCommitEvent() dispatches a compositioncommit event or + * compositioncommitasis event. If aCommitString is null, dispatches + * compositioncommitasis event. I.e., if aCommitString is null, this + * commits the composition with the last data. Otherwise, commits the + * composition with aCommitString value. + */ + bool DispatchCompositionCommitEvent(const nsAString* aCommitString = nullptr); /** * SetMarkedText() is a handler of setMarkedText of NSTextInput. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/TextInputHandler.mm thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/TextInputHandler.mm --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/cocoa/TextInputHandler.mm 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/cocoa/TextInputHandler.mm 2014-11-26 21:46:06.000000000 +0000 @@ -2691,18 +2691,17 @@ bool IMEInputHandler::DispatchCompositionChangeEvent(const nsString& aText, NSAttributedString* aAttrString, - NSRange& aSelectedRange, - bool aDoCommit) + NSRange& aSelectedRange) { PR_LOG(gLog, PR_LOG_ALWAYS, ("%p IMEInputHandler::DispatchCompositionChangeEvent, " "aText=\"%s\", aAttrString=\"%s\", " "aSelectedRange={ location=%llu, length=%llu }, " - "aDoCommit=%s, Destroyed()=%s", + "Destroyed()=%s", this, NS_ConvertUTF16toUTF8(aText).get(), GetCharacters([aAttrString string]), aSelectedRange.location, aSelectedRange.length, - TrueOrFalse(aDoCommit), TrueOrFalse(Destroyed()))); + TrueOrFalse(Destroyed()))); NS_ENSURE_TRUE(!Destroyed(), false); @@ -2712,14 +2711,37 @@ mWidget); compositionChangeEvent.time = PR_IntervalNow(); compositionChangeEvent.mData = aText; - if (!aDoCommit) { - compositionChangeEvent.mRanges = - CreateTextRangeArray(aAttrString, aSelectedRange); - } - mLastDispatchedCompositionString = compositionChangeEvent.mData; + compositionChangeEvent.mRanges = + CreateTextRangeArray(aAttrString, aSelectedRange); return DispatchEvent(compositionChangeEvent); } +bool +IMEInputHandler::DispatchCompositionCommitEvent(const nsAString* aCommitString) +{ + PR_LOG(gLog, PR_LOG_ALWAYS, + ("%p IMEInputHandler::DispatchCompositionCommitEvent, " + "aCommitString=0x%p (\"%s\"), Destroyed()=%s", + this, aCommitString, + aCommitString ? NS_ConvertUTF16toUTF8(*aCommitString).get() : "", + TrueOrFalse(Destroyed()))); + + if (NS_WARN_IF(Destroyed())) { + return false; + } + + nsRefPtr kungFuDeathGrip(this); + + uint32_t message = + aCommitString ? NS_COMPOSITION_COMMIT : NS_COMPOSITION_COMMIT_AS_IS; + WidgetCompositionEvent compositionCommitEvent(true, message, mWidget); + compositionCommitEvent.time = PR_IntervalNow(); + if (aCommitString) { + compositionCommitEvent.mData = *aCommitString; + } + return DispatchEvent(compositionCommitEvent); +} + void IMEInputHandler::InitCompositionEvent(WidgetCompositionEvent& aCompositionEvent) { @@ -2758,11 +2780,7 @@ if (IsIMEComposing() && aReplacementRange && aReplacementRange->location != NSNotFound && !NSEqualRanges(MarkedRange(), *aReplacementRange)) { - NSString* latestStr = - nsCocoaUtils::ToNSString(mLastDispatchedCompositionString); - NSAttributedString* attrLatestStr = - [[[NSAttributedString alloc] initWithString:latestStr] autorelease]; - InsertTextAsCommittingComposition(attrLatestStr, nullptr); + DispatchCompositionCommitEvent(); if (Destroyed()) { PR_LOG(gLog, PR_LOG_ALWAYS, ("%p IMEInputHandler::InsertTextAsCommittingComposition, " @@ -2770,6 +2788,7 @@ this)); return; } + OnEndIMEComposition(); } nsRefPtr kungFuDeathGrip(this); @@ -2801,25 +2820,11 @@ OnStartIMEComposition(); } - NSRange range = NSMakeRange(0, str.Length()); - DispatchCompositionChangeEvent(str, aAttrString, range, true); + DispatchCompositionCommitEvent(&str); if (Destroyed()) { PR_LOG(gLog, PR_LOG_ALWAYS, ("%p IMEInputHandler::InsertTextAsCommittingComposition, " - "destroyed by compositionchange event", this)); - return; - } - - OnUpdateIMEComposition([aAttrString string]); - - WidgetCompositionEvent compEnd(true, NS_COMPOSITION_END, mWidget); - InitCompositionEvent(compEnd); - compEnd.mData = mLastDispatchedCompositionString; - DispatchEvent(compEnd); - if (Destroyed()) { - PR_LOG(gLog, PR_LOG_ALWAYS, - ("%p IMEInputHandler::InsertTextAsCommittingComposition, " - "destroyed by compositionend event", this)); + "destroyed by compositioncommit event", this)); return; } @@ -2862,13 +2867,9 @@ if (IsIMEComposing() && aReplacementRange && aReplacementRange->location != NSNotFound && !NSEqualRanges(MarkedRange(), *aReplacementRange)) { - NSString* latestStr = - nsCocoaUtils::ToNSString(mLastDispatchedCompositionString); - NSAttributedString* attrLatestStr = - [[[NSAttributedString alloc] initWithString:latestStr] autorelease]; bool ignoreIMECommit = mIgnoreIMECommit; mIgnoreIMECommit = false; - InsertTextAsCommittingComposition(attrLatestStr, nullptr); + DispatchCompositionCommitEvent(); mIgnoreIMECommit = ignoreIMECommit; if (Destroyed()) { PR_LOG(gLog, PR_LOG_ALWAYS, @@ -2877,6 +2878,7 @@ this)); return; } + OnEndIMEComposition(); } nsString str; @@ -2908,32 +2910,32 @@ OnStartIMEComposition(); } - if (IsIMEComposing()) { + if (!IsIMEComposing()) { + return; + } + + if (!str.IsEmpty()) { OnUpdateIMEComposition([aAttrString string]); - bool doCommit = str.IsEmpty(); - DispatchCompositionChangeEvent(str, aAttrString, aSelectedRange, doCommit); + DispatchCompositionChangeEvent(str, aAttrString, aSelectedRange); if (Destroyed()) { PR_LOG(gLog, PR_LOG_ALWAYS, ("%p IMEInputHandler::SetMarkedText, " "destroyed by compositionchange event", this)); - return; } + return; + } - if (doCommit) { - WidgetCompositionEvent compEnd(true, NS_COMPOSITION_END, mWidget); - InitCompositionEvent(compEnd); - compEnd.mData = mLastDispatchedCompositionString; - DispatchEvent(compEnd); - if (Destroyed()) { - PR_LOG(gLog, PR_LOG_ALWAYS, - ("%p IMEInputHandler::SetMarkedText, " - "destroyed by compositionend event", this)); - return; - } - OnEndIMEComposition(); - } + // If the composition string becomes empty string, we should commit + // current composition. + DispatchCompositionCommitEvent(&EmptyString()); + if (Destroyed()) { + PR_LOG(gLog, PR_LOG_ALWAYS, + ("%p IMEInputHandler::SetMarkedText, " + "destroyed by compositioncommit event", this)); + return; } + OnEndIMEComposition(); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -3335,8 +3337,6 @@ NS_ASSERTION(!mIsIMEComposing, "There is a composition already"); mIsIMEComposing = true; - mLastDispatchedCompositionString.Truncate(); - NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -3380,8 +3380,6 @@ mIMECompositionString = nullptr; } - mLastDispatchedCompositionString.Truncate(); - NS_OBJC_END_TRY_ABORT_BLOCK; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/EventForwards.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/EventForwards.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/EventForwards.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/EventForwards.h 2014-11-26 21:46:06.000000000 +0000 @@ -102,6 +102,7 @@ #undef NS_ROOT_EVENT_CLASS // BasicEvents.h +struct BaseEventFlags; struct EventFlags; // TextEvents.h diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/GfxInfoBase.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/GfxInfoBase.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/GfxInfoBase.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/GfxInfoBase.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -90,7 +90,11 @@ using namespace mozilla::widget; using namespace mozilla; +#ifdef XP_MACOSX +NS_IMPL_ISUPPORTS(GfxInfoBase, nsIGfxInfo, nsIGfxInfo2, nsIObserver, nsISupportsWeakReference) +#else NS_IMPL_ISUPPORTS(GfxInfoBase, nsIGfxInfo, nsIObserver, nsISupportsWeakReference) +#endif #define BLACKLIST_PREF_BRANCH "gfx.blacklist." #define SUGGESTED_VERSION_PREF BLACKLIST_PREF_BRANCH "suggested-driver-version" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/GfxInfoBase.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/GfxInfoBase.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/GfxInfoBase.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/GfxInfoBase.h 2014-11-26 21:46:06.000000000 +0000 @@ -9,6 +9,9 @@ #define __mozilla_widget_GfxInfoBase_h__ #include "nsIGfxInfo.h" +#ifdef XP_MACOSX +#include "nsIGfxInfo2.h" +#endif #include "nsCOMPtr.h" #include "nsIObserver.h" #include "nsWeakReference.h" @@ -25,6 +28,9 @@ namespace widget { class GfxInfoBase : public nsIGfxInfo, +#ifdef XP_MACOSX + public nsIGfxInfo2, +#endif public nsIObserver, public nsSupportsWeakReference #ifdef DEBUG diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/GfxInfoWebGL.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/GfxInfoWebGL.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/GfxInfoWebGL.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/GfxInfoWebGL.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -29,7 +29,7 @@ else return NS_ERROR_INVALID_ARG; nsCOMPtr webgl = - do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=experimental-webgl"); + do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=webgl"); if (!webgl) return NS_ERROR_NOT_AVAILABLE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/GeckoTouchDispatcher.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/GeckoTouchDispatcher.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/GeckoTouchDispatcher.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/GeckoTouchDispatcher.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -53,8 +53,6 @@ GeckoTouchDispatcher::GeckoTouchDispatcher() : mTouchQueueLock("GeckoTouchDispatcher::mTouchQueueLock") , mTouchEventsFiltered(false) - , mTouchTimeDiff(0) - , mLastTouchTime(TimeStamp::Now()) { // Since GeckoTouchDispatcher is initialized when input is initialized // and reads gfxPrefs, it is the first thing to touch gfxPrefs. @@ -69,7 +67,7 @@ gfxPrefs::HardwareVsyncEnabled(); mVsyncAdjust = TimeDuration::FromMilliseconds(gfxPrefs::TouchVsyncSampleAdjust()); mMaxPredict = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleMaxPredict()); - mMinResampleTime = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleMinTime()); + mOldTouchThreshold = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleOldTouchThreshold()); mDelayedVsyncThreshold = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleVsyncDelayThreshold()); sTouchDispatcher = this; ClearOnShutdown(&sTouchDispatcher); @@ -147,8 +145,6 @@ MutexAutoLock lock(mTouchQueueLock); if (mResamplingEnabled) { mTouchMoveEvents.push_back(aTouch); - mTouchTimeDiff = aEventTime - mLastTouchTime; - mLastTouchTime = aEventTime; return; } @@ -178,19 +174,17 @@ if (mResamplingEnabled) { int touchCount = mTouchMoveEvents.size(); - // Both aVsynctime and mLastTouchTime are uint64_t - // Need to store as a signed int. - TimeDuration vsyncTouchDiff = aVsyncTime - mLastTouchTime; - bool resample = (touchCount > 1) && - (vsyncTouchDiff > mMinResampleTime); + TimeDuration vsyncTouchDiff = aVsyncTime - mTouchMoveEvents.back().mTimeStamp; // The delay threshold is a positive pref, but we're testing to see if the // vsync time is delayed from the touch, so add a negative sign. bool isDelayedVsyncEvent = vsyncTouchDiff < -mDelayedVsyncThreshold; + bool isOldTouch = vsyncTouchDiff > mOldTouchThreshold; + bool resample = (touchCount > 1) && !isDelayedVsyncEvent && !isOldTouch; if (!resample) { touchMove = mTouchMoveEvents.back(); mTouchMoveEvents.clear(); - if (!isDelayedVsyncEvent) { + if (!isDelayedVsyncEvent && !isOldTouch) { mTouchMoveEvents.push_back(touchMove); } } else { @@ -300,10 +294,11 @@ mTouchMoveEvents.push_back(currentTouch); TimeStamp sampleTime = aVsyncTime - mVsyncAdjust; + TimeDuration touchDiff = currentTouch.mTimeStamp - baseTouch.mTimeStamp; - if (mLastTouchTime < sampleTime) { - TimeDuration maxResampleTime = std::min(mTouchTimeDiff / 2, mMaxPredict); - TimeStamp maxTimestamp = mLastTouchTime + maxResampleTime; + if (currentTouch.mTimeStamp < sampleTime) { + TimeDuration maxResampleTime = std::min(touchDiff / 2, mMaxPredict); + TimeStamp maxTimestamp = currentTouch.mTimeStamp + maxResampleTime; if (sampleTime > maxTimestamp) { sampleTime = maxTimestamp; #ifdef LOG_RESAMPLE_DATA @@ -312,7 +307,7 @@ } } - ResampleTouch(aOutTouch, baseTouch, currentTouch, sampleTime - (mLastTouchTime - mTouchTimeDiff), mTouchTimeDiff); + ResampleTouch(aOutTouch, baseTouch, currentTouch, sampleTime - baseTouch.mTimeStamp, touchDiff); // Both mTimeStamp and mTime are being updated to sampleTime here. // mTime needs to be updated using a delta since TimeStamp doesn't diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/GeckoTouchDispatcher.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/GeckoTouchDispatcher.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/GeckoTouchDispatcher.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/GeckoTouchDispatcher.h 2014-11-26 21:46:06.000000000 +0000 @@ -73,14 +73,11 @@ // resample TimeDuration mMinResampleTime; - // The time difference between the last two touch move events - TimeDuration mTouchTimeDiff; - - // The system time at which the last touch event occured - TimeStamp mLastTouchTime; - // Threshold if a vsync event runs too far behind touch events TimeDuration mDelayedVsyncThreshold; + + // How far ahead can vsync events get ahead of touch events. + TimeDuration mOldTouchThreshold; }; } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/HwcComposer2D.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/HwcComposer2D.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/HwcComposer2D.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/HwcComposer2D.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -29,12 +29,6 @@ #include "mozilla/StaticPtr.h" #include "cutils/properties.h" #include "gfx2DGlue.h" -#include "GeckoTouchDispatcher.h" - -#ifdef MOZ_ENABLE_PROFILER_SPS -#include "GeckoProfiler.h" -#include "ProfilerMarkers.h" -#endif #if ANDROID_VERSION >= 17 #include "libdisplay/FramebufferSurface.h" @@ -237,19 +231,12 @@ void HwcComposer2D::Vsync(int aDisplay, nsecs_t aVsyncTimestamp) { - TimeStamp vsyncTime = mozilla::TimeStamp(aVsyncTimestamp); + TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(aVsyncTimestamp); nsecs_t vsyncInterval = aVsyncTimestamp - mLastVsyncTime; if (vsyncInterval < 16000000 || vsyncInterval > 17000000) { LOGE("Non-uniform vsync interval: %lld\n", vsyncInterval); } mLastVsyncTime = aVsyncTimestamp; - -#ifdef MOZ_ENABLE_PROFILER_SPS - if (profiler_is_active()) { - CompositorParent::PostInsertVsyncProfilerMarker(vsyncTime); - } -#endif - VsyncDispatcher::GetInstance()->NotifyVsync(vsyncTime); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/libdisplay/FramebufferSurface.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/libdisplay/FramebufferSurface.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/libdisplay/FramebufferSurface.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/libdisplay/FramebufferSurface.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -49,17 +49,20 @@ * This implements the (main) framebuffer management. This class * was adapted from the version in SurfaceFlinger */ -FramebufferSurface::FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, - sp& bq) : +FramebufferSurface::FramebufferSurface(int disp, + uint32_t width, + uint32_t height, + uint32_t format, + const sp& sc) #if ANDROID_VERSION >= 19 - ConsumerBase(bq, true), + : ConsumerBase(sc, true) #else - ConsumerBase(bq), + : ConsumerBase(sc) #endif - mDisplayType(disp), - mCurrentBufferSlot(-1), - mCurrentBuffer(0), - lastHandle(0) + , mDisplayType(disp) + , mCurrentBufferSlot(-1) + , mCurrentBuffer(0) + , lastHandle(0) { mName = "FramebufferSurface"; @@ -113,7 +116,7 @@ err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); #endif - if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) { + if (err != NO_ERROR && err != StreamConsumer::STALE_BUFFER_SLOT) { ALOGE("error releasing buffer: %s (%d)", strerror(-err), err); return err; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/libdisplay/FramebufferSurface.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/libdisplay/FramebufferSurface.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/libdisplay/FramebufferSurface.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/libdisplay/FramebufferSurface.h 2014-11-26 21:46:06.000000000 +0000 @@ -30,11 +30,17 @@ class String8; class HWComposer; +#if ANDROID_VERSION >= 21 +typedef IGraphicBufferConsumer StreamConsumer; +#else +typedef BufferQueue StreamConsumer; +#endif + // --------------------------------------------------------------------------- class FramebufferSurface : public ConsumerBase { public: - FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, sp& bq); + FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, const sp& sc); bool isUpdateOnDemand() const { return false; } status_t setUpdateRectangle(const Rect& updateRect); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/libdisplay/GonkDisplayJB.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/libdisplay/GonkDisplayJB.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/libdisplay/GonkDisplayJB.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/libdisplay/GonkDisplayJB.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -106,22 +106,33 @@ mAlloc = new GraphicBufferAlloc(); status_t error; - -#if ANDROID_VERSION >= 19 - sp bq = new BufferQueue(mAlloc); +#if ANDROID_VERSION >= 21 + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer, mAlloc); +#elif ANDROID_VERSION >= 19 + sp consumer = new BufferQueue(mAlloc); + sp producer = consumer; +#elif ANDROID_VERSION >= 18 + sp consumer = new BufferQueue(true, mAlloc); + sp producer = consumer; #else - sp bq = new BufferQueue(true, mAlloc); + sp consumer = new BufferQueue(true, mAlloc); #endif - mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, bq); + mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, consumer); #if ANDROID_VERSION == 17 - sp stc = new SurfaceTextureClient(static_cast >(mFBSurface->getBufferQueue())); + sp stc = new SurfaceTextureClient( + static_cast >(mFBSurface->getBufferQueue())); #else - sp stc = new Surface(static_cast >(bq)); + sp stc = new Surface(producer); #endif mSTClient = stc; mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_BUFFER_COUNT, 2); - mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE, GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); + mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE, + GRALLOC_USAGE_HW_FB | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_COMPOSER); mList = (hwc_display_contents_1_t *)malloc(sizeof(*mList) + (sizeof(hwc_layer_1_t)*2)); if (mHwc) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/nsAppShell.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/nsAppShell.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/nsAppShell.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/nsAppShell.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -715,7 +715,7 @@ int32_t action = args->action & AMOTION_EVENT_ACTION_MASK; int touchCount = args->pointerCount; MOZ_ASSERT(touchCount <= MAX_POINTERS); - TimeStamp timestamp = TimeStamp(args->eventTime); + TimeStamp timestamp = mozilla::TimeStamp::FromSystemTime(args->eventTime); Modifiers modifiers = getDOMModifiers(args->metaState); MultiTouchInput::MultiTouchType touchType = MultiTouchInput::MULTITOUCH_CANCEL; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/nsWindow.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/nsWindow.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/nsWindow.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/nsWindow.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -455,7 +455,7 @@ } NS_IMETHODIMP -nsWindow::MakeFullScreen(bool aFullScreen) +nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) { if (mWindowType != eWindowType_toplevel) { // Ignore fullscreen request for non-toplevel windows. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/nsWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/nsWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gonk/nsWindow.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gonk/nsWindow.h 2014-11-26 21:46:06.000000000 +0000 @@ -95,7 +95,7 @@ } NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); - NS_IMETHOD MakeFullScreen(bool aFullScreen) /*MOZ_OVERRIDE*/; + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) /*MOZ_OVERRIDE*/; virtual mozilla::TemporaryRef StartRemoteDrawing() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/mozgtk/mozgtk.c thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/mozgtk/mozgtk.c --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/mozgtk/mozgtk.c 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/mozgtk/mozgtk.c 2014-11-26 21:46:07.000000000 +0000 @@ -121,6 +121,7 @@ STUB(gdk_x11_screen_get_xscreen) STUB(gdk_x11_visual_get_xvisual) STUB(gdk_x11_window_lookup_for_display) +STUB(gdk_x11_window_set_user_time) STUB(gdk_x11_xatom_to_atom) STUB(gtk_accel_label_new) STUB(gtk_alignment_get_type) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsGtkIMModule.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsGtkIMModule.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsGtkIMModule.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsGtkIMModule.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -369,8 +369,7 @@ // IM. For compromising this issue, we should dispatch // compositionend event, however, we don't need to reset IM // actually. - DispatchCompositionEventsForCommit(activeContext, - EmptyString()); + DispatchCompositionCommitEvent(activeContext, &EmptyString()); filterThisEvent = false; } } else { @@ -749,7 +748,7 @@ } // Be aware, widget can be gone - DispatchCompositionEventsForCommit(aContext, mDispatchedCompositionString); + DispatchCompositionCommitEvent(aContext); } /* static */ @@ -921,7 +920,7 @@ NS_ConvertUTF8toUTF16 str(commitString); // Be aware, widget can be gone - DispatchCompositionEventsForCommit(aContext, str); + DispatchCompositionCommitEvent(aContext, &str); } void @@ -1096,14 +1095,15 @@ } bool -nsGtkIMModule::DispatchCompositionEventsForCommit( +nsGtkIMModule::DispatchCompositionCommitEvent( GtkIMContext* aContext, - const nsAString& aCommitString) + const nsAString* aCommitString) { PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, - ("GtkIMModule(%p): DispatchCompositionEventsForCommit, aContext=%p, " - "aCommitString=\"%s\"", - this, aContext, NS_ConvertUTF16toUTF8(aCommitString).get())); + ("GtkIMModule(%p): DispatchCompositionCommitEvent, aContext=%p, " + "aCommitString=%p, (\"%s\")", + this, aContext, aCommitString, + aCommitString ? NS_ConvertUTF16toUTF8(*aCommitString).get() : "")); if (!mLastFocusedWindow) { PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, @@ -1112,7 +1112,7 @@ } if (!IsComposing()) { - if (aCommitString.IsEmpty()) { + if (!aCommitString || aCommitString->IsEmpty()) { PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, (" FAILED, there is no composition and empty commit " "string")); @@ -1128,56 +1128,28 @@ nsRefPtr lastFocusedWindow(mLastFocusedWindow); - // First, dispatch a compositionchange event for committing with - // aCommitString. - mCompositionState = - eCompositionState_CommitCompositionChangeEventDispatched; - - WidgetCompositionEvent compositionChangeEvent(true, NS_COMPOSITION_CHANGE, - mLastFocusedWindow); - InitEvent(compositionChangeEvent); - compositionChangeEvent.mData = aCommitString; - - nsEventStatus status = nsEventStatus_eIgnore; - mLastFocusedWindow->DispatchEvent(&compositionChangeEvent, status); - - if (!IsComposing()) { - PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, - (" FAILED, there is no composition during dispatching " - "a compositionchange event for committing the composition")); - if (lastFocusedWindow->IsDestroyed() || - lastFocusedWindow != mLastFocusedWindow) { - PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, - (" NOTE, the focused widget was destroyed/changed by " - "compositionchange event")); - return false; - } - return true; - } - - // Next, forget current composition before dispatching a composionend event. + uint32_t message = aCommitString ? NS_COMPOSITION_COMMIT : + NS_COMPOSITION_COMMIT_AS_IS; mCompositionState = eCompositionState_NotComposing; mCompositionStart = UINT32_MAX; mCompositionTargetOffset = UINT32_MAX; mDispatchedCompositionString.Truncate(); - // Finally, dispatch a compositionend event if it's possible. - if (!lastFocusedWindow->IsDestroyed() && - lastFocusedWindow == mLastFocusedWindow) { - WidgetCompositionEvent compositionEndEvent(true, NS_COMPOSITION_END, - mLastFocusedWindow); - InitEvent(compositionEndEvent); - compositionEndEvent.mData = aCommitString; - - status = nsEventStatus_eIgnore; - mLastFocusedWindow->DispatchEvent(&compositionEndEvent, status); + WidgetCompositionEvent compositionCommitEvent(true, message, + mLastFocusedWindow); + InitEvent(compositionCommitEvent); + if (message == NS_COMPOSITION_COMMIT) { + compositionCommitEvent.mData = *aCommitString; } + nsEventStatus status = nsEventStatus_eIgnore; + mLastFocusedWindow->DispatchEvent(&compositionCommitEvent, status); + if (lastFocusedWindow->IsDestroyed() || lastFocusedWindow != mLastFocusedWindow) { PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, (" NOTE, the focused widget was destroyed/changed by " - "compositionend event")); + "compositioncommit event")); return false; } @@ -1493,7 +1465,7 @@ bool editorHadCompositionString = EditorHasCompositionString(); if (wasComposing) { selOffset = mCompositionStart; - if (!DispatchCompositionEventsForCommit(aContext, mSelectedString)) { + if (!DispatchCompositionCommitEvent(aContext, &mSelectedString)) { PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, (" FAILED, quitting from DeletText")); return NS_ERROR_FAILURE; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsGtkIMModule.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsGtkIMModule.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsGtkIMModule.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsGtkIMModule.h 2014-11-26 21:46:07.000000000 +0000 @@ -128,8 +128,7 @@ enum eCompositionState { eCompositionState_NotComposing, eCompositionState_CompositionStartDispatched, - eCompositionState_CompositionChangeEventDispatched, - eCompositionState_CommitCompositionChangeEventDispatched + eCompositionState_CompositionChangeEventDispatched }; eCompositionState mCompositionState; @@ -164,8 +163,6 @@ return "CompositionStartDispatched"; case eCompositionState_CompositionChangeEventDispatched: return "CompositionChangeEventDispatched"; - case eCompositionState_CommitCompositionChangeEventDispatched: - return "CommitCompositionChangeEventDispatched"; default: return "InvaildState"; } @@ -317,7 +314,7 @@ * FALSE, callers cannot continue the composition. * - DispatchCompositionStart * - DispatchCompositionChangeEvent - * - DispatchCompositionEventsForCommit + * - DispatchCompositionCommitEvent */ /** @@ -341,17 +338,19 @@ const nsAString& aCompositionString); /** - * Dispatches a compositionchange event for committing the composition - * string and a compositionend event. + * Dispatches a compositioncommit event or compositioncommitasis event. * * @param aContext A GtkIMContext which is being handled. - * @param aCommitString The string which the composition is - * committed with. + * @param aCommitString If this is nullptr, the composition will + * be committed with last dispatched data. + * Otherwise, the composition will be + * committed with this value. * @return true if the focused widget is neither * destroyed nor changed. Otherwise, false. */ - bool DispatchCompositionEventsForCommit(GtkIMContext* aContext, - const nsAString& aCommitString); + bool DispatchCompositionCommitEvent( + GtkIMContext* aContext, + const nsAString* aCommitString = nullptr); }; #endif // __nsGtkIMModule_h__ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsWindow.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsWindow.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsWindow.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsWindow.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -1295,13 +1295,7 @@ } if (sn_launchee_context_get_id_has_timestamp(ctx)) { - PRLibrary* gtkLibrary; - SetUserTimeFunc setUserTimeFunc = (SetUserTimeFunc) - PR_FindFunctionSymbolAndLibrary("gdk_x11_window_set_user_time", >kLibrary); - if (setUserTimeFunc) { - setUserTimeFunc(gdkWindow, sn_launchee_context_get_timestamp(ctx)); - PR_UnloadLibrary(gtkLibrary); - } + gdk_x11_window_set_user_time(gdkWindow, sn_launchee_context_get_timestamp(ctx)); } sn_launchee_context_setup_window(ctx, gdk_x11_window_get_xid(gdkWindow)); @@ -4710,7 +4704,7 @@ } NS_IMETHODIMP -nsWindow::MakeFullScreen(bool aFullScreen) +nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) { LOG(("nsWindow::MakeFullScreen [%p] aFullScreen %d\n", (void *)this, aFullScreen)); @@ -6011,12 +6005,79 @@ return updatePreference; } +bool +nsWindow::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + DoCommandCallback aCallback, + void* aCallbackData, + uint32_t aGeckoKeyCode, + uint32_t aNativeKeyCode) +{ + WidgetKeyboardEvent modifiedEvent(aEvent); + modifiedEvent.keyCode = aGeckoKeyCode; + static_cast(modifiedEvent.mNativeKeyEvent)->keyval = + aNativeKeyCode; + + NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); + return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData); +} + NS_IMETHODIMP_(bool) nsWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent, DoCommandCallback aCallback, void* aCallbackData) { + if (aEvent.keyCode >= nsIDOMKeyEvent::DOM_VK_LEFT && + aEvent.keyCode <= nsIDOMKeyEvent::DOM_VK_DOWN) { + + // Check if we're targeting content with vertical writing mode, + // and if so remap the arrow keys. + WidgetQueryContentEvent query(true, NS_QUERY_SELECTED_TEXT, this); + nsEventStatus status; + DispatchEvent(&query, status); + + if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) { + uint32_t geckoCode = 0; + uint32_t gdkCode = 0; + switch (aEvent.keyCode) { + case nsIDOMKeyEvent::DOM_VK_LEFT: + if (query.mReply.mWritingMode.IsVerticalLR()) { + geckoCode = nsIDOMKeyEvent::DOM_VK_UP; + gdkCode = GDK_Up; + } else { + geckoCode = nsIDOMKeyEvent::DOM_VK_DOWN; + gdkCode = GDK_Down; + } + break; + + case nsIDOMKeyEvent::DOM_VK_RIGHT: + if (query.mReply.mWritingMode.IsVerticalLR()) { + geckoCode = nsIDOMKeyEvent::DOM_VK_DOWN; + gdkCode = GDK_Down; + } else { + geckoCode = nsIDOMKeyEvent::DOM_VK_UP; + gdkCode = GDK_Up; + } + break; + + case nsIDOMKeyEvent::DOM_VK_UP: + geckoCode = nsIDOMKeyEvent::DOM_VK_LEFT; + gdkCode = GDK_Left; + break; + + case nsIDOMKeyEvent::DOM_VK_DOWN: + geckoCode = nsIDOMKeyEvent::DOM_VK_RIGHT; + gdkCode = GDK_Right; + break; + } + + return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback, + aCallbackData, + geckoCode, gdkCode); + } + } + NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); return keyBindings->Execute(aEvent, aCallback, aCallbackData); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/gtk/nsWindow.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/gtk/nsWindow.h 2014-11-26 21:46:07.000000000 +0000 @@ -146,7 +146,7 @@ bool aIntersectWithExisting) MOZ_OVERRIDE; virtual bool HasPendingInputEvent(); - NS_IMETHOD MakeFullScreen(bool aFullScreen); + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr); NS_IMETHOD HideWindowChrome(bool aShouldHide); /** @@ -263,6 +263,13 @@ const InputContextAction& aAction); NS_IMETHOD_(InputContext) GetInputContext(); virtual nsIMEUpdatePreference GetIMEUpdatePreference(); + bool ExecuteNativeKeyBindingRemapped( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + DoCommandCallback aCallback, + void* aCallbackData, + uint32_t aGeckoKeyCode, + uint32_t aNativeKeyCode); NS_IMETHOD_(bool) ExecuteNativeKeyBinding( NativeKeyBindingsType aType, const mozilla::WidgetKeyboardEvent& aEvent, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/InputData.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/InputData.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/InputData.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/InputData.h 2014-11-26 21:46:06.000000000 +0000 @@ -27,13 +27,15 @@ MULTITOUCH_INPUT, PANGESTURE_INPUT, PINCHGESTURE_INPUT, - TAPGESTURE_INPUT + TAPGESTURE_INPUT, + SCROLLWHEEL_INPUT }; class MultiTouchInput; class PanGestureInput; class PinchGestureInput; class TapGestureInput; +class ScrollWheelInput; // This looks unnecessary now, but as we add more and more classes that derive // from InputType (eventually probably almost as many as *Events.h has), it @@ -72,6 +74,7 @@ INPUTDATA_AS_CHILD_TYPE(PanGestureInput, PANGESTURE_INPUT) INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT) INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT) + INPUTDATA_AS_CHILD_TYPE(ScrollWheelInput, SCROLLWHEEL_INPUT) InputData() { @@ -431,6 +434,60 @@ ParentLayerPoint mLocalPoint; }; +// Encapsulation class for scroll-wheel events. These are generated by mice +// with physical scroll wheels, and on Windows by most touchpads when using +// scroll gestures. +class ScrollWheelInput : public InputData +{ +public: + enum ScrollDeltaType + { + // There are three kinds of scroll delta modes in Gecko: "page", "line" and + // "pixel". For apz, we currently only support "line" mode. + SCROLLDELTA_LINE + }; + + enum ScrollMode + { + SCROLLMODE_INSTANT, + SCROLLMODE_SMOOTH + }; + + ScrollWheelInput(uint32_t aTime, + TimeStamp aTimeStamp, + Modifiers aModifiers, + ScrollMode aScrollMode, + ScrollDeltaType aDeltaType, + const ScreenPoint& aOrigin, + double aDeltaX, + double aDeltaY) + : InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers), + mDeltaType(aDeltaType), + mScrollMode(aScrollMode), + mOrigin(aOrigin), + mDeltaX(aDeltaX), + mDeltaY(aDeltaY) + {} + + ScrollDeltaType mDeltaType; + ScrollMode mScrollMode; + ScreenPoint mOrigin; + + // Deltas are in units corresponding to the delta type. For line deltas, they + // are the number of line units to scroll. The number of device pixels for a + // horizontal and vertical line unit are in FrameMetrics::mLineScrollAmount. + // + // The horizontal (X) delta is > 0 for scrolling right and < 0 for scrolling + // left. The vertical (Y) delta is < 0 for scrolling up and > 0 for + // scrolling down. + double mDeltaX; + double mDeltaY; + + // The location of the scroll in local coordinates. This is set and used by + // APZ. + ParentLayerPoint mLocalOrigin; +}; + } #endif // InputData_h__ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/moz.build 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/moz.build 2014-11-26 21:46:07.000000000 +0000 @@ -29,6 +29,7 @@ ] elif toolkit == 'cocoa': XPIDL_SOURCES += [ + 'nsIGfxInfo2.idl', 'nsIMacDockSupport.idl', 'nsIMacWebAppUtils.idl', 'nsIStandaloneNativeMenu.idl', diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsBaseDragService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsBaseDragService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsBaseDragService.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsBaseDragService.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -648,7 +648,7 @@ nsBaseDragService::ConvertToUnscaledDevPixels(nsPresContext* aPresContext, int32_t* aScreenX, int32_t* aScreenY) { - int32_t adj = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel(); + int32_t adj = aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); *aScreenX = nsPresContext::CSSPixelsToAppUnits(*aScreenX) / adj; *aScreenY = nsPresContext::CSSPixelsToAppUnits(*aScreenY) / adj; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsBaseWidget.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsBaseWidget.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsBaseWidget.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsBaseWidget.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -42,7 +42,6 @@ #include "mozilla/gfx/2D.h" #include "mozilla/MouseEvents.h" #include "GLConsts.h" -#include "LayerScope.h" #include "mozilla/unused.h" #ifdef ACCESSIBILITY @@ -172,8 +171,6 @@ void nsBaseWidget::DestroyCompositor() { - LayerScope::DeInit(); - if (mCompositorChild) { mCompositorChild->SendWillStop(); mCompositorChild->Destroy(); @@ -741,7 +738,7 @@ // Put the window into full-screen mode // //------------------------------------------------------------------------- -NS_IMETHODIMP nsBaseWidget::MakeFullScreen(bool aFullScreen) +NS_IMETHODIMP nsBaseWidget::MakeFullScreen(bool aFullScreen, nsIScreen* aScreen) { HideWindowChrome(aFullScreen); @@ -761,12 +758,16 @@ screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1"); NS_ASSERTION(screenManager, "Unable to grab screenManager."); if (screenManager) { - nsCOMPtr screen; - screenManager->ScreenForRect(mOriginalBounds->x, - mOriginalBounds->y, - mOriginalBounds->width, - mOriginalBounds->height, - getter_AddRefs(screen)); + nsCOMPtr screen = aScreen; + if (!screen) { + // no screen was passed in, use the one that the window is on + screenManager->ScreenForRect(mOriginalBounds->x, + mOriginalBounds->y, + mOriginalBounds->width, + mOriginalBounds->height, + getter_AddRefs(screen)); + } + if (screen) { int32_t left, top, width, height; if (NS_SUCCEEDED(screen->GetRectDisplayPix(&left, &top, &width, &height))) { @@ -937,9 +938,6 @@ return; } - // Initialize LayerScope on the main thread. - LayerScope::Init(); - mCompositorParent = NewCompositorParent(aWidth, aHeight); MessageChannel *parentChannel = mCompositorParent->GetIPCChannel(); nsRefPtr lm = new ClientLayerManager(this); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsBaseWidget.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsBaseWidget.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsBaseWidget.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsBaseWidget.h 2014-11-26 21:46:07.000000000 +0000 @@ -127,7 +127,7 @@ virtual void SetShowsFullScreenButton(bool aShow) {} virtual void SetWindowAnimationType(WindowAnimationType aType) {} NS_IMETHOD HideWindowChrome(bool aShouldHide); - NS_IMETHOD MakeFullScreen(bool aFullScreen); + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aScreen = nullptr); virtual nsDeviceContext* GetDeviceContext(); virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsFilePickerProxy.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsFilePickerProxy.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsFilePickerProxy.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsFilePickerProxy.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -136,8 +136,13 @@ { mCallback = aCallback; - SendOpen(mSelectedType, mAddToRecentDocs, mDefault, - mDefaultExtension, mFilters, mFilterNames); + nsString displayDirectory; + if (mDisplayDirectory) { + mDisplayDirectory->GetPath(displayDirectory); + } + + SendOpen(mSelectedType, mAddToRecentDocs, mDefault, mDefaultExtension, + mFilters, mFilterNames, displayDirectory); return NS_OK; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsIGfxInfo2.idl thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsIGfxInfo2.idl --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsIGfxInfo2.idl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsIGfxInfo2.idl 2014-11-26 21:46:07.000000000 +0000 @@ -0,0 +1,24 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" + +/** + * nsIGfxInfo2 is a separately implemented extension of nsIGfxInfo, to + * allow us (in effect) to tack things onto the nsIGfxInfo interface + * without changing it. + */ + +[scriptable, uuid(9C8D8F44-6D52-45AA-8921-734EF4DF5DFE)] +interface nsIGfxInfo2 : nsISupports +{ + /** + * Not really Gfx-related. Here for convenience, + * possibly only temporarily. See bug 1102295. + */ + readonly attribute DOMString countryCode; +}; + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsIWidget.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsIWidget.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/nsIWidget.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/nsIWidget.h 2014-11-26 21:46:07.000000000 +0000 @@ -33,6 +33,7 @@ class ViewWrapper; class nsIWidgetListener; class nsIntRegion; +class nsIScreen; namespace mozilla { namespace dom { @@ -1405,9 +1406,12 @@ /** * Put the toplevel window into or out of fullscreen mode. - * + * If aTargetScreen is given, attempt to go fullscreen on that screen, + * if possible. (If not, it behaves as if aTargetScreen is null.) + * If !aFullScreen, aTargetScreen is ignored. + * aTargetScreen support is currently only implemented on Windows. */ - NS_IMETHOD MakeFullScreen(bool aFullScreen) = 0; + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) = 0; /** * Invalidate a specified rect for a widget so that it will be repainted diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/PuppetWidget.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/PuppetWidget.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/PuppetWidget.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/PuppetWidget.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -331,7 +331,8 @@ aStatus = mAttachedWidgetListener->HandleEvent(event, mUseAttachedEvents); } - if (event->message == NS_COMPOSITION_END) { + if (event->mClass == eCompositionEventClass && + event->AsCompositionEvent()->CausesDOMCompositionEndEvent()) { mIMEComposing = false; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/moz.build 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/moz.build 2014-11-26 21:46:07.000000000 +0000 @@ -42,7 +42,7 @@ if CONFIG['MOZ_X11']: LOCAL_INCLUDES += [ - '../shared/x11', + '../x11', ] #DEFINES['DEBUG_WIDGETS'] = True diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/nsPrintSettingsQt.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/nsPrintSettingsQt.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/nsPrintSettingsQt.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/nsPrintSettingsQt.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -291,15 +291,9 @@ NS_IMETHODIMP nsPrintSettingsQt::GetPaperName(char16_t** aPaperName) { - PR_STATIC_ASSERT(sizeof(indexToPaperName)/ - sizeof(char*) == QPrinter::NPageSize); - PR_STATIC_ASSERT(sizeof(indexToQtPaperEnum)/ - sizeof(QPrinter::PageSize) == QPrinter::NPageSize); - QPrinter::PaperSize size = mQPrinter->paperSize(); QString name(indexToPaperName[size]); - *aPaperName = ToNewUnicode(nsDependentString - ((const char16_t*)name.constData())); + *aPaperName = ToNewUnicode(nsDependentString((const char16_t*)name.constData())); return NS_OK; } @@ -307,7 +301,7 @@ nsPrintSettingsQt::SetPaperName(const char16_t* aPaperName) { QString ref((QChar*)aPaperName, NS_strlen(aPaperName)); - for (uint32_t i = 0; i < QPrinter::NPageSize; i++) + for (uint32_t i = 0; i < sizeof(indexToPaperName)/sizeof(char*); i++) { if (ref == QString(indexToPaperName[i])) { mQPrinter->setPageSize(indexToQtPaperEnum[i]); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/nsWindow.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/nsWindow.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/nsWindow.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/nsWindow.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -732,7 +732,7 @@ } NS_IMETHODIMP -nsWindow::MakeFullScreen(bool aFullScreen) +nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) { NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/nsWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/nsWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/qt/nsWindow.h 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/qt/nsWindow.h 2014-11-26 21:46:07.000000000 +0000 @@ -134,7 +134,7 @@ } NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); - NS_IMETHOD MakeFullScreen(bool aFullScreen); + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr); virtual mozilla::layers::LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/test_assign_event_data.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/test_assign_event_data.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/test_assign_event_data.html 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/test_assign_event_data.html 2014-11-26 21:46:07.000000000 +0000 @@ -186,16 +186,7 @@ "caret": { "start": 1, "length": 0 } }); synthesizeKey("a", { type: "keyup" }); - synthesizeCompositionChange({ "composition": - { "string": "\u306D", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - synthesizeComposition({ type: "compositionend", data: "\u732B" }); + synthesizeComposition({ type: "compositioncommitasis" }); }, canRun: function () { return true; @@ -218,16 +209,7 @@ "caret": { "start": 1, "length": 0 } }); synthesizeKey("VK_RETURN", { type: "keydown" }); - synthesizeCompositionChange({ "composition": - { "string": "\u306D", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - synthesizeComposition({ type: "compositionend", data: "\u732B" }); + synthesizeComposition({ type: "compositioncommitasis" }); synthesizeKey("VK_RETURN", { type: "keyup" }); }, canRun: function () { @@ -288,16 +270,7 @@ document.getElementById(this.targetID).value = ""; document.getElementById(this.targetID).focus(); synthesizeComposition({ type: "compositionstart" }); - synthesizeCompositionChange({ "composition": - { "string": "\u306D", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - synthesizeComposition({ type: "compositionend", data: "\u732B" }); + synthesizeComposition({ type: "compositioncommit", data: "\u306D" }); }, canRun: function () { return true; @@ -310,16 +283,7 @@ document.getElementById(this.targetID).value = ""; document.getElementById(this.targetID).focus(); synthesizeComposition({ type: "compositionstart" }); - synthesizeCompositionChange({ "composition": - { "string": "\u30E9\u30FC\u30E1\u30F3", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 4, "length": 0 } - }); - synthesizeComposition({ type: "compositionend", data: "\u30E9\u30FC\u30E1\u30F3" }); + synthesizeComposition({ type: "compositioncommit", data: "\u30E9\u30FC\u30E1\u30F3" }); }, canRun: function () { return true; @@ -363,16 +327,7 @@ { description: "InternalEditorInputEvent (input at committing)", targetID: "input-text", eventType: "input", dispatchEvent: function () { - synthesizeCompositionChange({ "composition": - { "string": "\u30E9\u30FC\u30E1\u30F3", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 4, "length": 0 } - }); - synthesizeComposition({ type: "compositionend", data: "\u30E9\u30FC\u30E1\u30F3" }); + synthesizeComposition({ type: "compositioncommitasis" }); }, canRun: function () { return true; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/test_imestate.html thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/test_imestate.html --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/test_imestate.html 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/test_imestate.html 2014-11-26 21:46:07.000000000 +0000 @@ -1266,18 +1266,7 @@ description + "#3 IME isn't enabled on HTML editor"); // cancel the composition - synthesizeCompositionChange( - { "composition": - { "string": "", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 0, "length": 0 } - }); - - synthesizeComposition({ type: "compositionend", data: "" }); + synthesizeComposition({ type: "compositioncommit", data: "" }); container.removeAttribute("contenteditable"); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/test_input_events_on_deactive_window.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/test_input_events_on_deactive_window.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/test_input_events_on_deactive_window.xul 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/test_input_events_on_deactive_window.xul 2014-11-26 21:46:07.000000000 +0000 @@ -195,17 +195,8 @@ "query selected text event returns wrong selected text"); clear(); // commit composition - synthesizeCompositionChange( - { "composition": - { "string": "\u3089", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - checkCompositionEvents(false, false, false, false, "commit composition"); + synthesizeComposition({ type: "compositioncommitasis" }); + checkCompositionEvents(false, true, false, true, "commit composition as is"); queryText = synthesizeQueryTextContent(0, 100); ok(queryText, "query text event result is null after commit"); if (!queryText) { @@ -232,9 +223,6 @@ is(querySelectedText.text, "", "query selected text event returns wrong selected text after commit"); clear(); - // end composition - synthesizeComposition({ type: "compositionend", data: "\u3089" }); - checkCompositionEvents(false, true, false, true, "compositionend"); } textarea.removeEventListener("keydown", onEvent, false); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/window_composition_text_querycontent.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/window_composition_text_querycontent.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/tests/window_composition_text_querycontent.xul 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/tests/window_composition_text_querycontent.xul 2014-11-26 21:46:07.000000000 +0000 @@ -230,19 +230,7 @@ }); // commit - synthesizeCompositionChange( - { "composition": - { "string": "\u732B", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - - // end composition - synthesizeComposition({ type: "compositionend", data: "\u732B" }); + synthesizeComposition({ type: "compositioncommitasis" }); // start composition synthesizeComposition({ type: "compositionstart" }); @@ -260,19 +248,7 @@ }); // cancel the composition - synthesizeCompositionChange( - { "composition": - { "string": "", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 0, "length": 0 } - }); - - // end composition - synthesizeComposition({ type: "compositionend", data: "" }); + synthesizeComposition({ type: "compositioncommit", data: "" }); // start composition synthesizeComposition({ type: "compositionstart" }); @@ -325,19 +301,7 @@ }); // commit - synthesizeCompositionChange( - { "composition": - { "string": "\u5A18", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - - // end composition - synthesizeComposition({ type: "compositionend", data: "\u5A18" }); + synthesizeComposition({ type: "compositioncommitasis" }); synthesizeKey(" ", {}); synthesizeKey("m", {}); @@ -433,19 +397,7 @@ }); // commit - synthesizeCompositionChange( - { "composition": - { "string": "\u5996\u602a", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 2, "length": 0 } - }); - - // end composition - synthesizeComposition({ type: "compositionend", data: "\u5996\u602a" }); + synthesizeComposition({ type: "compositioncommitasis" }); synthesizeKey("VK_BACK_SPACE", {}); synthesizeKey("VK_BACK_SPACE", {}); @@ -614,6 +566,343 @@ } } +function runCompositionCommitAsIsTest() +{ + textarea.focus(); + + var result = {}; + function clearResult() + { + result = { compositionupdate: false, compositionend: false, text: false, input: false } + } + + function handler(aEvent) + { + result[aEvent.type] = true; + } + + textarea.addEventListener("compositionupdate", handler, true); + textarea.addEventListener("compositionend", handler, true); + textarea.addEventListener("input", handler, true); + textarea.addEventListener("text", handler, true); + + // compositioncommitasis with composing string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have composition string #1"); + + clearResult(); + synthesizeComposition({ type: "compositioncommitasis" }); + + is(result.compositionupdate, false, "runCompositionCommitAsIsTest: compositionupdate shouldn't be fired after dispatching compositioncommitasis #1"); + is(result.compositionend, true, "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #1"); + is(result.text, true, "runCompositionCommitAsIsTest: text should be fired after dispatching compositioncommitasis because it's dispatched when there is composing string #1"); + is(result.input, true, "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #1"); + is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #1"); + + // compositioncommitasis with committed string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have composition string #2"); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #2"); + + clearResult(); + synthesizeComposition({ type: "compositioncommitasis" }); + + is(result.compositionupdate, false, "runCompositionCommitAsIsTest: compositionupdate shouldn't be fired after dispatching compositioncommitasis #2"); + is(result.compositionend, true, "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #2"); + is(result.text, false, "runCompositionCommitAsIsTest: text shouldn't be fired after dispatching compositioncommitasis because it's dispatched when there is already committed string #2"); + is(result.input, true, "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #2"); + is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #2"); + + // compositioncommitasis with committed string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have composition string #3"); + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }); + is(textarea.value, "", "runCompositionCommitAsIsTest: textarea has non-empty composition string #3"); + + clearResult(); + synthesizeComposition({ type: "compositioncommitasis" }); + + is(result.compositionupdate, false, "runCompositionCommitAsIsTest: compositionupdate shouldn't be fired after dispatching compositioncommitasis #3"); + is(result.compositionend, true, "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #3"); + is(result.text, false, "runCompositionCommitAsIsTest: text shouldn't be fired after dispatching compositioncommitasis because it's dispatched when there is empty composition string #3"); + is(result.input, true, "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #3"); + is(textarea.value, "", "runCompositionCommitAsIsTest: textarea doesn't have committed string #3"); + + textarea.removeEventListener("compositionupdate", handler, true); + textarea.removeEventListener("compositionend", handler, true); + textarea.removeEventListener("input", handler, true); + textarea.removeEventListener("text", handler, true); +} + +function runCompositionCommitTest() +{ + textarea.focus(); + + var result = {}; + function clearResult() + { + result = { compositionupdate: false, compositionend: false, text: false, input: false } + } + + function handler(aEvent) + { + result[aEvent.type] = true; + } + + textarea.addEventListener("compositionupdate", handler, true); + textarea.addEventListener("compositionend", handler, true); + textarea.addEventListener("input", handler, true); + textarea.addEventListener("text", handler, true); + + // compositioncommit with different composing string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #1"); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "\u3043" }); + + is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #1"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #1"); + is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit because it's dispatched when there is compoing string #1"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #1"); + is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #1"); + + // compositioncommit with different committed string when there is already committed string + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #2"); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have committed string #2"); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "\u3043" }); + + is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #2"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #2"); + is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #2"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #2"); + is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #2"); + + // compositioncommit with empty composition string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #3"); + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }); + is(textarea.value, "", "runCompositionCommitTest: textarea has non-empty composition string #3"); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "\u3043" }); + + is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #3"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #3"); + is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #3"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #3"); + is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #3"); + + // compositioncommit with non-empty composition string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #4"); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "" }); + + is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #4"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #4"); + is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #4"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #4"); + is(textarea.value, "", "runCompositionCommitTest: textarea should be empty #4"); + + // compositioncommit immediately after compositionstart + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "\u3042" }); + + is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #5"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #5"); + is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #5"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #5"); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should be empty #5"); + + // compositioncommit with same composition string. + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #5"); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "\u3042" }); + + is(result.compositionupdate, false, "runCompositionCommitTest: compositionupdate shouldn't be fired after dispatching compositioncommit #5"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #5"); + is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit because there was composition string #5"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #5"); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should have committed string #5"); + + // compositioncommit with same composition string when there is committed string + textarea.value = ""; + synthesizeComposition({ type: "compositionstart" }); + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #6"); + + synthesizeCompositionChange( + { "composition": + { "string": "\u3042", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #6"); + + clearResult(); + synthesizeComposition({ type: "compositioncommit", data: "\u3042" }); + + is(result.compositionupdate, false, "runCompositionCommitTest: compositionupdate shouldn't be fired after dispatching compositioncommit #6"); + is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #6"); + is(result.text, false, "runCompositionCommitTest: text shouldn't be fired after dispatching compositioncommit because there was already committed string #6"); + is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #6"); + is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should have committed string #6"); + + textarea.removeEventListener("compositionupdate", handler, true); + textarea.removeEventListener("compositionend", handler, true); + textarea.removeEventListener("input", handler, true); + textarea.removeEventListener("text", handler, true); +} + function runCompositionTest() { textarea.value = ""; @@ -978,16 +1267,7 @@ } // commit the composition string - synthesizeCompositionChange( - { "composition": - { "string": "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 8, "length": 0 } - }); + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046", "runCompositionTest", "#1-13") || @@ -995,9 +1275,6 @@ return; } - synthesizeComposition({ type: "compositionend", - data: "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046" }); - var textRect3 = synthesizeQueryTextRect(0, 1); var textRect4 = synthesizeQueryTextRect(1, 1); @@ -1084,16 +1361,7 @@ } // commit the composition string - synthesizeCompositionChange( - { "composition": - { "string": "\u3058\u3087\u3046", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 3, "length": 0 } - }); + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046", "runCompositionTest", "#2-4") || @@ -1101,8 +1369,6 @@ return; } - synthesizeComposition({ type: "compositionend", data: "\u3058\u3087\u3046" }); - // set selection var selectionSetTest = synthesizeSelectionSet(4, 7, false); ok(selectionSetTest, "runCompositionTest: selectionSetTest failed"); @@ -1168,18 +1434,7 @@ } // cancel the composition - synthesizeCompositionChange( - { "composition": - { "string": "", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 0, "length": 0 } - }); - - synthesizeComposition({ type: "compositionend", data: "" }); + synthesizeComposition({ type: "compositioncommit", data: "" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3", "runCompositionTest", "#3-5") || @@ -1226,31 +1481,13 @@ return; } - synthesizeCompositionChange( - { "composition": - { "string": "\u6700", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - + synthesizeComposition({ type: "compositioncommit", data: "\u6700" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700", "runCompositionTest", "#4-3") || !checkSelection(5, "", "runCompositionTest", "#4-3")) { return; } - synthesizeComposition({ type: "compositionend", data: "\u6700" }); - - if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700", - "runCompositionTest", "#4-4") || - !checkSelection(5, "", "runCompositionTest", "#4-4")) { - return; - } - // testing the canceling case synthesizeComposition({ type: "compositionstart" }); @@ -1271,16 +1508,7 @@ return; } - synthesizeCompositionChange( - { "composition": - { "string": "", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 0, "length": 0 } - }); + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700", "runCompositionTest", "#4-6") || @@ -1288,14 +1516,6 @@ return; } - synthesizeComposition({ type: "compositionend", data: "\u6700" }); - - if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700", - "runCompositionTest", "#4-7") || - !checkSelection(5, "", "runCompositionTest", "#4-7")) { - return; - } - // testing whether the empty composition string deletes selected string. synthesizeKey("VK_LEFT", { shiftKey: true }); @@ -1318,31 +1538,13 @@ return; } - synthesizeCompositionChange( - { "composition": - { "string": "\u9AD8", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - + synthesizeComposition({ type: "compositioncommit", data: "\u9AD8" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8", "runCompositionTest", "#4-9") || !checkSelection(5, "", "runCompositionTest", "#4-9")) { return; } - synthesizeComposition({ type: "compositionend", data: "\u9AD8" }); - - if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8", - "runCompositionTest", "#4-10") || - !checkSelection(5, "", "runCompositionTest", "#4-10")) { - return; - } - synthesizeKey("VK_BACK_SPACE", {}); if (!checkContent("\u30E9\u30FC\u30E1\u30F3", "runCompositionTest", "#4-11") || @@ -1388,31 +1590,13 @@ return; } - synthesizeCompositionChange( - { "composition": - { "string": "", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 0, "length": 0 } - }); - + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("\u30E9\u30FC\u30E1\u30F3", "runCompositionTest", "#5-3") || !checkSelection(4, "", "runCompositionTest", "#5-3")) { return; } - synthesizeComposition({ type: "compositionend", data: "\u9AD8" }); - - if (!checkContent("\u30E9\u30FC\u30E1\u30F3", - "runCompositionTest", "#5-4") || - !checkSelection(4, "", "runCompositionTest", "#5-4")) { - return; - } - // Undo tests for the testcases for bug 23558 and bug 271815 synthesizeKey("Z", { accelKey: true }); @@ -1639,18 +1823,7 @@ kDescription + "value of input element wasn't modified (input) #2"); // text event shouldn't cause composition update, e.g., at committing. - synthesizeCompositionChange( - { "composition": - { "string": "\u3089\u30FC", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 2, "length": 0 } - }); - - synthesizeComposition({ type: "compositionend", data: "\u3089\u30FC" }); + synthesizeComposition({ type: "compositioncommitasis" }); is(windowEventCounts["compositionstart"], 1, kDescription + "compositionstart has been handled more than once by window #3"); @@ -1702,18 +1875,7 @@ "caret": { "start": 1, "length": 0 } }); - synthesizeCompositionChange( - { "composition": - { "string": "\u3089", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - - synthesizeComposition({ type: "compositionend", data: "\u3089" }); + synthesizeComposition({ type: "compositioncommitasis" }); is(windowEventCounts["compositionstart"], 1, kDescription + "compositionstart hasn't been handled by window #4"); @@ -1782,18 +1944,7 @@ "caret": { "start": 1, "length": 0 } }); - synthesizeCompositionChange( - { "composition": - { "string": "\u306D", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - - synthesizeComposition({ type: "compositionend", data: "\u306D" }); + synthesizeComposition({ type: "compositioncommitasis" }); is(windowEventCounts["compositionstart"], 1, kDescription + "compositionstart hasn't been handled by window #5"); @@ -1864,18 +2015,7 @@ "caret": { "start": 1, "length": 0 } }); - synthesizeCompositionChange( - { "composition": - { "string": "\u306E", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - - synthesizeComposition({ type: "compositionend", data: "\u306E" }); + synthesizeComposition({ type: "compositioncommitasis" }); is(windowEventCounts["compositionstart"], 1, kDescription + "compositionstart hasn't been handled by window #6"); @@ -2741,23 +2881,32 @@ } } + function onComposition(aEvent) + { + if (aEvent.type == "compositionstart") { + expectedIsComposing = true; + } else if (aEvent.type == "compositionend") { + expectedIsComposing = false; + } + } + textarea.addEventListener("keydown", eventHandler, true); textarea.addEventListener("keypress", eventHandler, true); textarea.addEventListener("keyup", eventHandler, true); textarea.addEventListener("input", eventHandler, true); + textarea.addEventListener("compositionstart", onComposition, true); + textarea.addEventListener("compositionend", onComposition, true); textarea.focus(); textarea.value = ""; // XXX These cases shouldn't occur in actual native key events because we // don't dispatch key events while composition (bug 354358). - expectedIsComposing = false; description = "events before dispatching compositionstart"; synthesizeKey("VK_LEFT", {}); synthesizeKey("a", { type: "keydown" }); synthesizeComposition({ type: "compositionstart" }); - expectedIsComposing = true; description = "events after dispatching compositionstart"; synthesizeCompositionChange( { "composition": @@ -2776,28 +2925,20 @@ description = "events for committing composition string"; synthesizeKey("VK_RETURN", { type: "keydown" }); - synthesizeCompositionChange( - { "composition": - { "string": "\u3042", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); + + synthesizeComposition({ type: "compositioncommitasis" }); // input event will be fired by synthesizing compositionend event. // Then, its isComposing should be false. - expectedIsComposing = false; - description = "events after dispatching compositionend"; - synthesizeComposition({ type: "compositionend" }); + description = "events after dispatching compositioncommitasis"; synthesizeKey("VK_RETURN", { type: "keyup" }); textarea.removeEventListener("keydown", eventHandler, true); textarea.removeEventListener("keypress", eventHandler, true); textarea.removeEventListener("keyup", eventHandler, true); textarea.removeEventListener("input", eventHandler, true); + textarea.removeEventListener("compositionstart", onComposition, true); + textarea.removeEventListener("compositionend", onComposition, true); textarea.value = ""; } @@ -2972,24 +3113,12 @@ } // commit them - synthesizeCompositionChange( - { "composition": - { "string": "\u5909\u8EAB", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 2, "length": 0 } - }); - + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("\u5909\u8EAB", aTestName, "#1-4") || !checkSelection(2, "", aTestName, "#1-4")) { return; } - synthesizeComposition({ type: "compositionend", data: "\u5909\u8EAB" }); - is(aFocusedEditor.value, "\u5909\u8EAB", aTestName + ": composition isn't in the focused editor"); if (aFocusedEditor.value != "\u5909\u8EAB") { @@ -3261,25 +3390,12 @@ } // commit the composition string - synthesizeCompositionChange( - { "composition": - { "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 6, "length": 0 } - }); - + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("\u30E9", kDesc, "#1-11") || !checkSelection(1, "", kDesc, "#1-11")) { return; } - synthesizeComposition({ type: "compositionend", - data: "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8" }); - // restart composition synthesizeComposition({ type: "compositionstart" }); @@ -3301,24 +3417,12 @@ } // commit the composition string - synthesizeCompositionChange( - { "composition": - { "string": "\u3058", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); - + synthesizeComposition({ type: "compositioncommit", data: "\u3058" }); if (!checkContent("\u30E9", kDesc, "#2-2") || !checkSelection(1 + 0, "", kDesc, "#2-2")) { return; } - synthesizeComposition({ type: "compositionend", data: "\u3058" }); - // Undo synthesizeKey("Z", {accelKey: true}); @@ -3375,16 +3479,7 @@ } // commit the composition string - synthesizeCompositionChange( - { "composition": - { "string": "\u9B54", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 1, "length": 0 } - }); + synthesizeComposition({ type: "compositioncommitasis" }); // The input text must be discarded. Then, the caret position shouldn't be // updated from its position at compositionstart. @@ -3393,8 +3488,6 @@ return; } - synthesizeComposition({ type: "compositionend", data: "\u9B54" }); - // start composition synthesizeComposition({ type: "compositionstart" }); @@ -3416,23 +3509,12 @@ } // commit the composition string - synthesizeCompositionChange( - { "composition": - { "string": "\u9B54\u6CD5", - "clauses": - [ - { "length": 0, "attr": 0 } - ] - }, - "caret": { "start": 2, "length": 0 } - }); + synthesizeComposition({ type: "compositioncommitasis" }); if (!checkContent("X", kDesc, "#5-2") || !checkSelection(0, "", kDesc, "#5-2")) { return; } - - synthesizeComposition({ type: "compositionend", data: "\u9B54\u6CD5" }); } function runTest() @@ -3440,6 +3522,8 @@ textareaInFrame = iframe.contentDocument.getElementById("textarea"); runUndoRedoTest(); + runCompositionCommitAsIsTest(); + runCompositionCommitTest(); runCompositionTest(); runCompositionEventTest(); runCharAtPointTest(textarea, "textarea in the document"); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/TextEvents.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/TextEvents.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/TextEvents.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/TextEvents.h 2014-11-26 21:46:06.000000000 +0000 @@ -18,6 +18,7 @@ #include "nsRect.h" #include "nsStringGlue.h" #include "nsTArray.h" +#include "WritingModes.h" /****************************************************************************** * virtual keycode values @@ -341,6 +342,20 @@ { return mRanges ? mRanges->Length() : 0; } + + bool CausesDOMTextEvent() const + { + return message == NS_COMPOSITION_CHANGE || + message == NS_COMPOSITION_COMMIT || + message == NS_COMPOSITION_COMMIT_AS_IS; + } + + bool CausesDOMCompositionEndEvent() const + { + return message == NS_COMPOSITION_END || + message == NS_COMPOSITION_COMMIT || + message == NS_COMPOSITION_COMMIT_AS_IS; + } }; /****************************************************************************** @@ -455,6 +470,8 @@ bool mHasSelection; // true if DOM element under mouse belongs to widget bool mWidgetIsHit; + // mozilla::WritingMode value at the end (focus) of the selection + mozilla::WritingMode mWritingMode; // used by NS_QUERY_SELECTION_AS_TRANSFERABLE nsCOMPtr mTransferable; } mReply; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/VsyncDispatcher.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/VsyncDispatcher.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/VsyncDispatcher.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/VsyncDispatcher.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -8,6 +8,11 @@ #include "mozilla/layers/CompositorParent.h" #include "gfxPrefs.h" +#ifdef MOZ_ENABLE_PROFILER_SPS +#include "GeckoProfiler.h" +#include "ProfilerMarkers.h" +#endif + #ifdef MOZ_WIDGET_GONK #include "GeckoTouchDispatcher.h" #endif @@ -42,6 +47,12 @@ } void +VsyncDispatcher::SetVsyncSource(VsyncSource* aVsyncSource) +{ + mVsyncSource = aVsyncSource; +} + +void VsyncDispatcher::DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime) { // Touch events can sometimes start a composite, so make sure we dispatch touches @@ -57,6 +68,12 @@ VsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) { bool notifiedCompositors = false; +#ifdef MOZ_ENABLE_PROFILER_SPS + if (profiler_is_active()) { + CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp); + } +#endif + if (gfxPrefs::VsyncAlignedCompositor()) { MutexAutoLock lock(mCompositorObserverLock); notifiedCompositors = NotifyVsyncObservers(aVsyncTimestamp, mCompositorObservers); @@ -88,7 +105,7 @@ void VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver) { - MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread()); MutexAutoLock lock(mCompositorObserverLock); if (mCompositorObservers.Contains(aVsyncObserver)) { mCompositorObservers.RemoveElement(aVsyncObserver); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/VsyncDispatcher.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/VsyncDispatcher.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/VsyncDispatcher.h 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/VsyncDispatcher.h 2014-11-26 21:46:06.000000000 +0000 @@ -21,6 +21,19 @@ class CompositorVsyncObserver; } +// Controls how and when to enable/disable vsync. +class VsyncSource +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource) + virtual void EnableVsync() = 0; + virtual void DisableVsync() = 0; + virtual bool IsVsyncEnabled() = 0; + +protected: + virtual ~VsyncSource() {} +}; // VsyncSource + class VsyncObserver { // Must be destroyed on main thread since the compositor is as well @@ -34,7 +47,7 @@ protected: VsyncObserver() {} virtual ~VsyncObserver() {} -}; +}; // VsyncObserver // VsyncDispatcher is used to dispatch vsync events to the registered observers. class VsyncDispatcher @@ -44,7 +57,13 @@ public: static VsyncDispatcher* GetInstance(); // Called on the vsync thread when a hardware vsync occurs + // The aVsyncTimestamp can mean different things depending on the platform: + // b2g - The vsync timestamp of the previous frame that was just displayed + // OSX - The vsync timestamp of the upcoming frame + // TODO: Windows / Linux. DOCUMENT THIS WHEN IMPLEMENTING ON THOSE PLATFORMS + // Android: TODO void NotifyVsync(TimeStamp aVsyncTimestamp); + void SetVsyncSource(VsyncSource* aVsyncSource); // Compositor vsync observers must be added/removed on the compositor thread void AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver); @@ -61,7 +80,8 @@ // Can have multiple compositors. On desktop, this is 1 compositor per window Mutex mCompositorObserverLock; nsTArray> mCompositorObservers; -}; + nsRefPtr mVsyncSource; +}; // VsyncDispatcher } // namespace mozilla diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/WidgetEventImpl.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/WidgetEventImpl.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/WidgetEventImpl.cpp 2014-11-14 09:37:37.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/WidgetEventImpl.cpp 2014-11-26 21:46:06.000000000 +0000 @@ -140,6 +140,8 @@ case NS_COMPOSITION_END: case NS_COMPOSITION_UPDATE: case NS_COMPOSITION_CHANGE: + case NS_COMPOSITION_COMMIT_AS_IS: + case NS_COMPOSITION_COMMIT: return true; default: return false; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/GfxInfo.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/GfxInfo.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/GfxInfo.cpp 2014-11-14 09:37:38.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/GfxInfo.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -194,17 +194,6 @@ return retval; } -// The driver ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD, possibly -// followed by &REV_XXXX. We uppercase the string, and strip the &REV_ part -// from it, if found. -static void normalizeDriverId(nsString& driverid) { - ToUpperCase(driverid); - int32_t rev = driverid.Find(NS_LITERAL_CSTRING("&REV_")); - if (rev != -1) { - driverid.Cut(rev, driverid.Length()); - } -} - // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD // this function is used to extract the id's out of it uint32_t @@ -966,6 +955,13 @@ IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(7,15,10,1666)); IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(7,15,10,1666)); + // Bug 1074378 + APPEND_TO_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, + (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), + (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD), + GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, + DRIVER_EQUAL, V(8,15,10,1749), "8.15.10.2342"); + /* OpenGL on any Intel hardware is discouraged */ APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices, @@ -1013,12 +1009,6 @@ nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE_START, V(14,1,0,0), V(14,2,0,0), "ATI Catalyst 14.6+"); - // Disable D2D on some ATI drivers which don't support dxgi keyed mutex correctly (bug 1089183) - APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_ALL, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, - nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, - DRIVER_BETWEEN_INCLUSIVE_START, V(8,653,0,0), V(8,691,0,0), "ATI Catalyst 14.6+"); - /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches * whilst scrolling. See bugs: 612007, 644787 & 645872. */ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsIMM32Handler.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsIMM32Handler.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsIMM32Handler.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsIMM32Handler.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -489,12 +489,7 @@ NS_ConvertUTF16toUTF8(mCompositionString).get(), mCompositionString.IsEmpty() ? "" : ", but canceling it...")); - mCompositionString.Truncate(); - - nsIMEContext IMEContext(aWindow->GetWindowHandle()); - DispatchCompositionChangeEvent(aWindow, IMEContext, false); - - HandleEndComposition(aWindow); + HandleEndComposition(aWindow, &EmptyString()); return true; } @@ -953,7 +948,6 @@ } mCompositionStart = selection.mReply.mOffset; - mLastDispatchedCompositionString.Truncate(); WidgetCompositionEvent event(true, NS_COMPOSITION_START, aWindow); aWindow->InitEvent(event, &point); @@ -1012,13 +1006,12 @@ HandleStartComposition(aWindow, aIMEContext); } - GetCompositionString(aIMEContext, GCS_RESULTSTR); + GetCompositionString(aIMEContext, GCS_RESULTSTR, mCompositionString); PR_LOG(gIMM32Log, PR_LOG_ALWAYS, ("IMM32: HandleComposition, GCS_RESULTSTR\n")); - DispatchCompositionChangeEvent(aWindow, aIMEContext, false); - HandleEndComposition(aWindow); + HandleEndComposition(aWindow, &mCompositionString); if (!IS_COMPOSING_LPARAM(lParam)) { return ShouldDrawCompositionStringOurselves(); @@ -1039,27 +1032,31 @@ PR_LOG(gIMM32Log, PR_LOG_ALWAYS, ("IMM32: HandleComposition, GCS_COMPSTR\n")); - GetCompositionString(aIMEContext, GCS_COMPSTR); + nsAutoString previousCompositionString(mCompositionString); + GetCompositionString(aIMEContext, GCS_COMPSTR, mCompositionString); if (!IS_COMPOSING_LPARAM(lParam)) { PR_LOG(gIMM32Log, PR_LOG_ALWAYS, ("IMM32: HandleComposition, lParam doesn't indicate composing, " - "mCompositionString=\"%s\", mLastDispatchedCompositionString=\"%s\"", + "mCompositionString=\"%s\", previousCompositionString=\"%s\"", NS_ConvertUTF16toUTF8(mCompositionString).get(), - NS_ConvertUTF16toUTF8(mLastDispatchedCompositionString).get())); + NS_ConvertUTF16toUTF8(previousCompositionString).get())); // If composition string isn't changed, we can trust the lParam. // So, we need to do nothing. - if (mLastDispatchedCompositionString == mCompositionString) { + if (previousCompositionString == mCompositionString) { return ShouldDrawCompositionStringOurselves(); } // IME may send WM_IME_COMPOSITION without composing lParam values // when composition string becomes empty (e.g., using Backspace key). // If composition string is empty, we should dispatch a compositionchange - // event with empty string. + // event with empty string and clear the clause information. if (mCompositionString.IsEmpty()) { - DispatchCompositionChangeEvent(aWindow, aIMEContext, false); + mClauseArray.Clear(); + mAttributeArray.Clear(); + mCursorPosition = 0; + DispatchCompositionChangeEvent(aWindow, aIMEContext); return ShouldDrawCompositionStringOurselves(); } @@ -1205,7 +1202,8 @@ } void -nsIMM32Handler::HandleEndComposition(nsWindow* aWindow) +nsIMM32Handler::HandleEndComposition(nsWindow* aWindow, + const nsAString* aCommitString) { NS_PRECONDITION(mIsComposing, "HandleEndComposition is called but mIsComposing is FALSE"); @@ -1213,23 +1211,26 @@ "HandleComposition should not be called when a plug-in has focus"); PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: HandleEndComposition\n")); - - WidgetCompositionEvent event(true, NS_COMPOSITION_END, aWindow); - nsIntPoint point(0, 0); + ("IMM32: HandleEndComposition(aWindow=0x%p, aCommitString=0x%p (\"%s\"))", + aWindow, aCommitString, + aCommitString ? NS_ConvertUTF16toUTF8(*aCommitString).get() : "")); if (mNativeCaretIsCreated) { ::DestroyCaret(); mNativeCaretIsCreated = false; } - aWindow->InitEvent(event, &point); - // The last dispatched composition string must be the committed string. - event.mData = mLastDispatchedCompositionString; - aWindow->DispatchWindowEvent(&event); + uint32_t message = + aCommitString ? NS_COMPOSITION_COMMIT : NS_COMPOSITION_COMMIT_AS_IS; + WidgetCompositionEvent compositionCommitEvent(true, message, aWindow); + nsIntPoint point(0, 0); + aWindow->InitEvent(compositionCommitEvent, &point); + if (aCommitString) { + compositionCommitEvent.mData = *aCommitString; + } + aWindow->DispatchWindowEvent(&compositionCommitEvent); mIsComposing = false; mComposingWindow = nullptr; - mLastDispatchedCompositionString.Truncate(); } static void @@ -1513,7 +1514,6 @@ nsIMEContext IMEContext(mComposingWindow->GetWindowHandle()); NS_ASSERTION(IMEContext.IsValid(), "IME context must be valid"); - DispatchCompositionChangeEvent(mComposingWindow, IMEContext, false); HandleEndComposition(mComposingWindow); return true; } @@ -1567,18 +1567,15 @@ void nsIMM32Handler::DispatchCompositionChangeEvent(nsWindow* aWindow, - const nsIMEContext &aIMEContext, - bool aCheckAttr) + const nsIMEContext& aIMEContext) { NS_ASSERTION(mIsComposing, "conflict state"); PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: DispatchCompositionChangeEvent, aCheckAttr=%s\n", - aCheckAttr ? "TRUE": "FALSE")); + ("IMM32: DispatchCompositionChangeEvent")); - // If we don't need to draw composition string ourselves and this is not - // commit event (i.e., under composing), we don't need to fire - // compositionchange event during composing. - if (aCheckAttr && !ShouldDrawCompositionStringOurselves()) { + // If we don't need to draw composition string ourselves, we don't need to + // fire compositionchange event during composing. + if (!ShouldDrawCompositionStringOurselves()) { // But we need to adjust composition window pos and native caret pos, here. SetIMERelatedWindowsPos(aWindow, aIMEContext); return; @@ -1592,11 +1589,8 @@ aWindow->InitEvent(event, &point); - if (aCheckAttr) { - event.mRanges = CreateTextRangeArray(); - } - - event.mData = mLastDispatchedCompositionString = mCompositionString; + event.mRanges = CreateTextRangeArray(); + event.mData = mCompositionString; aWindow->DispatchWindowEvent(&event); @@ -1619,7 +1613,9 @@ nsRefPtr textRangeArray = new TextRangeArray(); TextRange range; - if (mClauseArray.Length() == 0) { + if (mCompositionString.IsEmpty()) { + // Don't append clause information if composition string is empty. + } else if (mClauseArray.Length() == 0) { // Some IMEs don't return clause array information, then, we assume that // all characters in the composition string are in one clause. range.mStartOffset = 0; @@ -1684,12 +1680,16 @@ void nsIMM32Handler::GetCompositionString(const nsIMEContext &aIMEContext, - DWORD aIndex) + DWORD aIndex, + nsAString& aCompositionString) const { + aCompositionString.Truncate(); + // Retrieve the size of the required output buffer. long lRtn = ::ImmGetCompositionStringW(aIMEContext.get(), aIndex, nullptr, 0); if (lRtn < 0 || - !mCompositionString.SetLength((lRtn / sizeof(WCHAR)) + 1, mozilla::fallible_t())) { + !aCompositionString.SetLength((lRtn / sizeof(WCHAR)) + 1, + mozilla::fallible_t())) { PR_LOG(gIMM32Log, PR_LOG_ALWAYS, ("IMM32: GetCompositionString, FAILED by OOM\n")); return; // Error or out of memory. @@ -1697,13 +1697,13 @@ // Actually retrieve the composition string information. lRtn = ::ImmGetCompositionStringW(aIMEContext.get(), aIndex, - (LPVOID)mCompositionString.BeginWriting(), + (LPVOID)aCompositionString.BeginWriting(), lRtn + sizeof(WCHAR)); - mCompositionString.SetLength(lRtn / sizeof(WCHAR)); + aCompositionString.SetLength(lRtn / sizeof(WCHAR)); PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: GetCompositionString, SUCCEEDED mCompositionString=\"%s\"\n", - NS_ConvertUTF16toUTF8(mCompositionString).get())); + ("IMM32: GetCompositionString, SUCCEEDED aCompositionString=\"%s\"\n", + NS_ConvertUTF16toUTF8(aCompositionString).get())); } bool diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsIMM32Handler.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsIMM32Handler.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsIMM32Handler.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsIMM32Handler.h 2014-11-26 21:46:07.000000000 +0000 @@ -227,7 +227,10 @@ const nsIMEContext &aIMEContext); bool HandleComposition(nsWindow* aWindow, const nsIMEContext &aIMEContext, LPARAM lParam); - void HandleEndComposition(nsWindow* aWindow); + // If aCommitString is null, this commits composition with the latest + // dispatched data. Otherwise, commits composition with the value. + void HandleEndComposition(nsWindow* aWindow, + const nsAString* aCommitString = nullptr); bool HandleReconvert(nsWindow* aWindow, LPARAM lParam, LRESULT *oResult); bool HandleQueryCharPosition(nsWindow* aWindow, LPARAM lParam, LRESULT *oResult); @@ -276,7 +279,9 @@ uint32_t aOffset, nsIntRect &aCharRect); bool GetCaretRect(nsWindow* aWindow, nsIntRect &aCaretRect); - void GetCompositionString(const nsIMEContext &aIMEContext, DWORD aIndex); + void GetCompositionString(const nsIMEContext &aIMEContext, + DWORD aIndex, + nsAString& aCompositionString) const; /** * Get the current target clause of composition string. * If there are one or more characters whose attribute is ATTR_TARGET_*, @@ -290,9 +295,18 @@ * in the composition string, you need to subtract mCompositionStart from it. */ bool GetTargetClauseRange(uint32_t *aOffset, uint32_t *aLength = nullptr); + + /** + * DispatchCompositionChangeEvent() dispatches NS_COMPOSITION_CHANGE event + * with clause information (it'll be retrieved by CreateTextRangeArray()). + * I.e., this should be called only during composing. If a composition is + * being committed, only HandleCompositionEnd() should be called. + * + * @param aWindow The window which has the composition. + * @param aIMEContext Native IME context which has the composition. + */ void DispatchCompositionChangeEvent(nsWindow* aWindow, - const nsIMEContext &aIMEContext, - bool aCheckAttr = true); + const nsIMEContext& aIMEContext); already_AddRefed CreateTextRangeArray(); nsresult EnsureClauseArray(int32_t aCount); @@ -335,7 +349,6 @@ nsWindow* mComposingWindow; nsString mCompositionString; - nsString mLastDispatchedCompositionString; InfallibleTArray mClauseArray; InfallibleTArray mAttributeArray; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsTextStore.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsTextStore.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsTextStore.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsTextStore.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -1674,24 +1674,12 @@ PR_LOG(sTextStoreLog, PR_LOG_DEBUG, ("TSF: 0x%p nsTextStore::FlushPendingActions(), " - "dispatching compositionchange event...", this)); - WidgetCompositionEvent compositionChange(true, NS_COMPOSITION_CHANGE, + "dispatching compositioncommit event...", this)); + WidgetCompositionEvent compositionCommit(true, NS_COMPOSITION_COMMIT, mWidget); - mWidget->InitEvent(compositionChange); - compositionChange.mData = action.mData; - mWidget->DispatchWindowEvent(&compositionChange); - if (!mWidget || mWidget->Destroyed()) { - break; - } - - PR_LOG(sTextStoreLog, PR_LOG_DEBUG, - ("TSF: 0x%p nsTextStore::FlushPendingActions(), " - "dispatching compositionend event...", this)); - WidgetCompositionEvent compositionEnd(true, NS_COMPOSITION_END, - mWidget); - compositionEnd.mData = compositionChange.mData; - mWidget->InitEvent(compositionEnd); - mWidget->DispatchWindowEvent(&compositionEnd); + mWidget->InitEvent(compositionCommit); + compositionCommit.mData = action.mData; + mWidget->DispatchWindowEvent(&compositionCommit); if (!mWidget || mWidget->Destroyed()) { break; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsToolkit.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsToolkit.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsToolkit.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsToolkit.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -33,6 +33,8 @@ } } +MouseTrailer* nsToolkit::gMouseTrailer; + //------------------------------------------------------------------------- // // constructor @@ -46,6 +48,8 @@ nsToolkit::Startup(GetModuleHandle(nullptr)); #endif + gMouseTrailer = &mMouseTrailer; + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { mD3D9Timer = do_CreateInstance("@mozilla.org/timer;1"); mD3D9Timer->InitWithFuncCallback(::StartAllowingD3D9, @@ -64,6 +68,7 @@ nsToolkit::~nsToolkit() { MOZ_COUNT_DTOR(nsToolkit); + gMouseTrailer = nullptr; } void @@ -105,3 +110,126 @@ return gToolkit; } + + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +MouseTrailer::MouseTrailer() : mMouseTrailerWindow(nullptr), mCaptureWindow(nullptr), + mIsInCaptureMode(false), mEnabled(true) +{ +} +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +MouseTrailer::~MouseTrailer() +{ + DestroyTimer(); +} +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::SetMouseTrailerWindow(HWND aWnd) +{ + if (mMouseTrailerWindow != aWnd && mTimer) { + // Make sure TimerProc is fired at least once for the old window + TimerProc(nullptr, nullptr); + } + mMouseTrailerWindow = aWnd; + CreateTimer(); +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::SetCaptureWindow(HWND aWnd) +{ + mCaptureWindow = aWnd; + if (mCaptureWindow) { + mIsInCaptureMode = true; + } +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +nsresult MouseTrailer::CreateTimer() +{ + if (mTimer || !mEnabled) { + return NS_OK; + } + + nsresult rv; + mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + return mTimer->InitWithFuncCallback(TimerProc, nullptr, 200, + nsITimer::TYPE_REPEATING_SLACK); +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::DestroyTimer() +{ + if (mTimer) { + mTimer->Cancel(); + mTimer = nullptr; + } +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::TimerProc(nsITimer* aTimer, void* aClosure) +{ + MouseTrailer *mtrailer = nsToolkit::gMouseTrailer; + NS_ASSERTION(mtrailer, "MouseTrailer still firing after deletion!"); + + // Check to see if we are in mouse capture mode, + // Once capture ends we could still get back one more timer event. + // Capture could end outside our window. + // Also, for some reason when the mouse is on the frame it thinks that + // it is inside the window that is being captured. + if (mtrailer->mCaptureWindow) { + if (mtrailer->mCaptureWindow != mtrailer->mMouseTrailerWindow) { + return; + } + } else { + if (mtrailer->mIsInCaptureMode) { + // mMouseTrailerWindow could be bad from rolling over the frame, so clear + // it if we were capturing and now this is the first timer callback + // since we canceled the capture + mtrailer->mMouseTrailerWindow = nullptr; + mtrailer->mIsInCaptureMode = false; + return; + } + } + + if (mtrailer->mMouseTrailerWindow && ::IsWindow(mtrailer->mMouseTrailerWindow)) { + POINT mp; + DWORD pos = ::GetMessagePos(); + mp.x = GET_X_LPARAM(pos); + mp.y = GET_Y_LPARAM(pos); + HWND mouseWnd = ::WindowFromPoint(mp); + if (mtrailer->mMouseTrailerWindow != mouseWnd) { + // Notify someone that a mouse exit happened. + PostMessage(mtrailer->mMouseTrailerWindow, WM_MOUSELEAVE, 0, 0); + + // we are out of this window, destroy timer + mtrailer->DestroyTimer(); + mtrailer->mMouseTrailerWindow = nullptr; + } + } else { + mtrailer->DestroyTimer(); + mtrailer->mMouseTrailerWindow = nullptr; + } +} + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsToolkit.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsToolkit.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsToolkit.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsToolkit.h 2014-11-26 21:46:07.000000000 +0000 @@ -21,6 +21,41 @@ #endif /** + * Makes sure exit/enter mouse messages are always dispatched. + * In the case where the mouse has exited the outer most window the + * only way to tell if it has exited is to set a timer and look at the + * mouse pointer to see if it is within the outer most window. + */ + +class MouseTrailer +{ +public: + HWND GetMouseTrailerWindow() { return mMouseTrailerWindow; } + HWND GetCaptureWindow() { return mCaptureWindow; } + + void SetMouseTrailerWindow(HWND aWnd); + void SetCaptureWindow(HWND aWnd); + void Disable() { mEnabled = false; DestroyTimer(); } + void Enable() { mEnabled = true; CreateTimer(); } + void DestroyTimer(); + + MouseTrailer(); + ~MouseTrailer(); +private: + + nsresult CreateTimer(); + + static void TimerProc(nsITimer* aTimer, void* aClosure); + + // Information for mouse enter/exit events + HWND mMouseTrailerWindow; + HWND mCaptureWindow; + bool mIsInCaptureMode; + bool mEnabled; + nsCOMPtr mTimer; +}; + +/** * Wrapper around the thread running the message pump. * The toolkit abstraction is necessary because the message pump must * execute within the same thread that created the widget under Win32. @@ -38,6 +73,7 @@ static nsToolkit* GetToolkit(); static HINSTANCE mDllInstance; + static MouseTrailer *gMouseTrailer; static void Startup(HMODULE hModule); static void Shutdown(); @@ -47,6 +83,7 @@ static nsToolkit* gToolkit; nsCOMPtr mD3D9Timer; + MouseTrailer mMouseTrailer; }; #endif // TOOLKIT_H diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsWindow.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsWindow.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsWindow.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsWindow.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -186,6 +186,9 @@ #define SM_CONVERTIBLESLATEMODE 0x2003 #endif +#include "mozilla/layers/CompositorParent.h" +#include "InputData.h" + using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::gfx; @@ -353,6 +356,7 @@ mUnicodeWidget = true; mDisplayPanFeedback = false; mTouchWindow = false; + mFutureMarginsToUse = false; mCustomNonClient = false; mHideChrome = false; mFullscreenMode = false; @@ -2848,7 +2852,7 @@ } NS_IMETHODIMP -nsWindow::MakeFullScreen(bool aFullScreen) +nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) { // taskbarInfo will be nullptr pre Windows 7 until Bug 680227 is resolved. nsCOMPtr taskbarInfo = @@ -2878,7 +2882,7 @@ // Will call hide chrome, reposition window. Note this will // also cache dimensions for restoration, so it should only // be called once per fullscreen request. - nsresult rv = nsBaseWidget::MakeFullScreen(aFullScreen); + nsresult rv = nsBaseWidget::MakeFullScreen(aFullScreen, aTargetScreen); if (visible) { Show(true); @@ -3139,20 +3143,19 @@ NS_METHOD nsWindow::CaptureMouse(bool aCapture) { - TRACKMOUSEEVENT mTrack; - mTrack.cbSize = sizeof(TRACKMOUSEEVENT); - mTrack.dwFlags = TME_LEAVE; - mTrack.dwHoverTime = 0; + if (!nsToolkit::gMouseTrailer) { + NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed"); + return NS_OK; + } + if (aCapture) { - mTrack.hwndTrack = mWnd; + nsToolkit::gMouseTrailer->SetCaptureWindow(mWnd); ::SetCapture(mWnd); } else { - mTrack.hwndTrack = nullptr; + nsToolkit::gMouseTrailer->SetCaptureWindow(nullptr); ::ReleaseCapture(); } sIsInMouseCapture = aCapture; - // Requests WM_MOUSELEAVE events for this window. - TrackMouseEvent(&mTrack); return NS_OK; } @@ -3737,10 +3740,50 @@ return ConvertStatus(status); } -bool nsWindow::DispatchScrollEvent(WidgetGUIEvent* event) +nsEventStatus nsWindow::MaybeDispatchAsyncWheelEvent(WidgetGUIEvent* aEvent) +{ + if (aEvent->mClass != eWheelEventClass) { + return nsEventStatus_eIgnore; + } + + WidgetWheelEvent* event = aEvent->AsWheelEvent(); + + // Otherwise, scroll-zoom won't work. + if (event->IsControl()) { + return nsEventStatus_eIgnore; + } + + + // Other scrolling modes aren't supported yet. + if (event->deltaMode != nsIDOMWheelEvent::DOM_DELTA_LINE) { + return nsEventStatus_eIgnore; + } + + ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT; + if (Preferences::GetBool("general.smoothScroll")) + scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH; + + ScreenPoint origin(event->refPoint.x, event->refPoint.y); + ScrollWheelInput input(event->time, event->timeStamp, 0, + scrollMode, + ScrollWheelInput::SCROLLDELTA_LINE, + origin, + event->lineOrPageDeltaX, + event->lineOrPageDeltaY); + + ScrollableLayerGuid ignoreGuid; + return mAPZC->ReceiveInputEvent(input, &ignoreGuid, nullptr); +} + +bool nsWindow::DispatchScrollEvent(WidgetGUIEvent* aEvent) { + if (mAPZC) { + if (MaybeDispatchAsyncWheelEvent(aEvent) == nsEventStatus_eConsumeNoDefault) + return true; + } + nsEventStatus status; - DispatchEvent(event, status); + DispatchEvent(aEvent, status); return ConvertStatus(status); } @@ -4018,7 +4061,12 @@ // call the event callback if (mWidgetListener) { + if (nsToolkit::gMouseTrailer) + nsToolkit::gMouseTrailer->Disable(); if (aEventType == NS_MOUSE_MOVE) { + if (nsToolkit::gMouseTrailer && !sIsInMouseCapture) { + nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd); + } nsIntRect rect; GetBounds(rect); rect.x = 0; @@ -4049,6 +4097,9 @@ result = DispatchWindowEvent(&event); + if (nsToolkit::gMouseTrailer) + nsToolkit::gMouseTrailer->Enable(); + // Release the widget with NS_IF_RELEASE() just in case // the context menu key code in EventListenerManager::HandleEvent() // released it already. @@ -6584,6 +6635,16 @@ IMEHandler::OnDestroyWindow(this); + // Turn off mouse trails if enabled. + MouseTrailer* mtrailer = nsToolkit::gMouseTrailer; + if (mtrailer) { + if (mtrailer->GetMouseTrailerWindow() == mWnd) + mtrailer->DestroyTimer(); + + if (mtrailer->GetCaptureWindow() == mWnd) + mtrailer->SetCaptureWindow(nullptr); + } + // Free GDI window class objects if (mBrush) { VERIFY(::DeleteObject(mBrush)); @@ -7655,6 +7716,19 @@ } } +CompositorParent* nsWindow::NewCompositorParent(int aSurfaceWidth, + int aSurfaceHeight) +{ + CompositorParent *compositor = new CompositorParent(this, false, aSurfaceWidth, aSurfaceHeight); + + if (gfxPrefs::AsyncPanZoomEnabled()) { + mAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId()); + APZCTreeManager::SetDPI(GetDPI()); + } + + return compositor; +} + /************************************************************** ************************************************************** ** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsWindowGfx.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsWindowGfx.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsWindowGfx.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsWindowGfx.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -379,8 +379,6 @@ gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface, IntSize(paintRect.right - paintRect.left, paintRect.bottom - paintRect.top)); - nsRefPtr thebesContext = new gfxContext(dt); - // don't need to double buffer with anything but GDI BufferMode doubleBuffering = mozilla::layers::BufferMode::BUFFER_NONE; if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) || @@ -396,9 +394,8 @@ case eTransparencyTransparent: // If we're rendering with translucency, we're going to be // rendering the whole window; make sure we clear it first - thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR); - thebesContext->Paint(); - thebesContext->SetOperator(gfxContext::OPERATOR_OVER); + dt->ClearRect(Rect(0.f, 0.f, + dt->GetSize().width, dt->GetSize().height)); break; } #else @@ -406,6 +403,8 @@ #endif } + nsRefPtr thebesContext = new gfxContext(dt); + { AutoLayerManagerSetup setupLayerManager(this, thebesContext, doubleBuffering); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsWindow.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsWindow.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/widget/windows/nsWindow.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/widget/windows/nsWindow.h 2014-11-26 21:46:07.000000000 +0000 @@ -40,10 +40,9 @@ #endif #include "nsUXThemeData.h" - #include "nsIDOMMouseEvent.h" - #include "nsIIdleServiceInternal.h" +#include "mozilla/layers/APZCTreeManager.h" /** * Forward class definitions @@ -75,6 +74,8 @@ typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview; typedef mozilla::widget::NativeKey NativeKey; typedef mozilla::widget::MSGResult MSGResult; + typedef mozilla::layers::APZCTreeManager APZCTreeManager; + public: nsWindow(); @@ -90,6 +91,7 @@ virtual bool DispatchScrollEvent(mozilla::WidgetGUIEvent* aEvent) MOZ_OVERRIDE; virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE; virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return mIsTopWidgetWindow; } + virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight) MOZ_OVERRIDE; // nsIWidget interface NS_IMETHOD Create(nsIWidget *aParent, @@ -127,7 +129,7 @@ uint32_t aHotspotX, uint32_t aHotspotY); NS_IMETHOD SetCursor(nsCursor aCursor); virtual nsresult ConfigureChildren(const nsTArray& aConfigurations); - NS_IMETHOD MakeFullScreen(bool aFullScreen); + NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aScreen = nullptr); NS_IMETHOD HideWindowChrome(bool aShouldHide); NS_IMETHOD Invalidate(bool aEraseBackground = false, bool aUpdateNCArea = false, @@ -390,6 +392,8 @@ void OnWindowPosChanging(LPWINDOWPOS& info); void OnSysColorChanged(); + nsEventStatus MaybeDispatchAsyncWheelEvent(mozilla::WidgetGUIEvent* aEvent); + /** * Function that registers when the user has been active (used for detecting * when the user is idle). @@ -591,6 +595,8 @@ static bool sNeedsToInitMouseWheelSettings; static void InitMouseWheelScrollData(); + + nsRefPtr mAPZC; }; /** diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/ErrorList.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/ErrorList.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/ErrorList.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/ErrorList.h 2014-11-26 21:46:07.000000000 +0000 @@ -631,6 +631,7 @@ /* ======================================================================= */ #define MODULE NS_ERROR_MODULE_SECURITY /* Error code for CSP */ + ERROR(NS_ERROR_CSP_FORM_ACTION_VIOLATION, FAILURE(98)), ERROR(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION, FAILURE(99)), /* CMS specific nsresult error codes. Note: the numbers used here correspond diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsConsoleService.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsConsoleService.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsConsoleService.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsConsoleService.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -31,6 +31,11 @@ #include #endif +#ifdef MOZ_TASK_TRACER +#include "GeckoTaskTracer.h" +using namespace mozilla::tasktracer; +#endif + using namespace mozilla; NS_IMPL_ADDREF(nsConsoleService) @@ -246,6 +251,17 @@ OutputDebugStringW(msg.get()); } #endif +#ifdef MOZ_TASK_TRACER + { + nsCString msg; + aMessage->ToString(msg); + int prefixPos = msg.Find(GetJSLabelPrefix()); + if (prefixPos >= 0) { + nsDependentCSubstring submsg(msg, prefixPos); + AddLabel("%s", submsg.BeginReading()); + } + } +#endif /* * If there's already a message in the slot we're about to replace, diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsMemoryInfoDumper.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsMemoryInfoDumper.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsMemoryInfoDumper.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsMemoryInfoDumper.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -760,6 +760,8 @@ } #ifdef MOZ_DMD +dmd::DMDFuncs::Singleton dmd::DMDFuncs::sSingleton; + nsresult nsMemoryInfoDumper::OpenDMDFile(const nsAString& aIdentifier, int aPid, FILE** aOutFile) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsMemoryReporterManager.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsMemoryReporterManager.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsMemoryReporterManager.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsMemoryReporterManager.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -952,8 +952,8 @@ sizes.mStackTraceTable, "Memory used by DMD's stack trace table."); - REPORT("explicit/dmd/block-table", - sizes.mBlockTable, + REPORT("explicit/dmd/live-block-table", + sizes.mLiveBlockTable, "Memory used by DMD's live block table."); #undef REPORT diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsSystemInfo.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsSystemInfo.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsSystemInfo.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsSystemInfo.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -45,7 +45,7 @@ #endif #if defined(XP_LINUX) && defined(MOZ_SANDBOX) -#include "mozilla/Sandbox.h" +#include "mozilla/SandboxInfo.h" #endif // Slot for NS_InitXPCOM2 to pass information to nsSystemInfo::Init. @@ -357,20 +357,19 @@ #endif #if defined(XP_LINUX) && defined(MOZ_SANDBOX) - SandboxFeatureFlags sandboxFlags = GetSandboxFeatureFlags(); + SandboxInfo sandInfo = SandboxInfo::Get(); + SetPropertyAsBool(NS_LITERAL_STRING("hasSeccompBPF"), - sandboxFlags & kSandboxFeatureSeccompBPF); + sandInfo.Test(SandboxInfo::kHasSeccompBPF)); - SandboxStatus sandboxContent = ContentProcessSandboxStatus(); - if (sandboxContent != kSandboxingDisabled) { + if (sandInfo.Test(SandboxInfo::kEnabledForContent)) { SetPropertyAsBool(NS_LITERAL_STRING("canSandboxContent"), - sandboxContent != kSandboxingWouldFail); + sandInfo.CanSandboxContent()); } - SandboxStatus sandboxMedia = MediaPluginSandboxStatus(); - if (sandboxMedia != kSandboxingDisabled) { + if (sandInfo.Test(SandboxInfo::kEnabledForMedia)) { SetPropertyAsBool(NS_LITERAL_STRING("canSandboxMedia"), - sandboxMedia != kSandboxingWouldFail); + sandInfo.CanSandboxMedia()); } #endif // XP_LINUX && MOZ_SANDBOX diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsWindowsHelpers.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsWindowsHelpers.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/base/nsWindowsHelpers.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/base/nsWindowsHelpers.h 2014-11-26 21:46:07.000000000 +0000 @@ -127,7 +127,7 @@ namespace { -bool +bool inline IsRunningInWindowsMetro() { static bool alreadyChecked = false; @@ -157,7 +157,7 @@ return isMetro; } -HMODULE +HMODULE inline LoadLibrarySystem32(LPCWSTR aModule) { WCHAR systemPath[MAX_PATH + 1] = { L'\0' }; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/nsXULAppAPI.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/nsXULAppAPI.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/nsXULAppAPI.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/nsXULAppAPI.h 2014-11-26 21:46:07.000000000 +0000 @@ -393,9 +393,16 @@ XRE_SetRemoteExceptionHandler, (const char* aPipe)) #endif +namespace mozilla { +namespace gmp { +class GMPLoader; +} // namespace gmp +} // namepsace mozilla + XRE_API(nsresult, XRE_InitChildProcess, (int aArgc, - char* aArgv[])) + char* aArgv[], + mozilla::gmp::GMPLoader* aGMPLoader)) XRE_API(GeckoProcessType, XRE_GetProcessType, ()) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposerBase.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposerBase.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposerBase.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposerBase.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -6,23 +6,27 @@ #include "mozilla/Mutex.h" #include "mozilla/Scoped.h" +#include "mozilla/UniquePtr.h" #include -#include #include "PoisonIOInterposer.h" +#ifdef MOZ_REPLACE_MALLOC +#include "replace_malloc_bridge.h" +#endif + // Auxiliary method to convert file descriptors to ids #if defined(XP_WIN32) #include inline intptr_t -FileDescriptorToID(int aFd) +FileDescriptorToHandle(int aFd) { return _get_osfhandle(aFd); } #else inline intptr_t -FileDescriptorToID(int aFd) +FileDescriptorToHandle(int aFd) { return aFd; } @@ -75,18 +79,133 @@ Lock = nullptr; } -// Return a vector used to hold the IDs of the current debug files. On unix +// The ChunkedList class implements, at the high level, a non-iterable +// list of instances of T. Its goal is to be somehow minimalist for the +// use case of storing the debug files handles here, with the property of +// not requiring a lock to look up whether it contains a specific value. +// It is also chunked in blocks of chunk_size bytes so that its +// initialization doesn't require a memory allocation, while keeping the +// possibility to increase its size as necessary. Note that chunks are +// never deallocated (except in the destructor). +// All operations are essentially O(N) but N is not expected to be large +// enough to matter. +template +class ChunkedList { + struct ListChunk { + static const size_t kLength = \ + (chunk_size - sizeof(ListChunk*)) / sizeof(mozilla::Atomic); + + mozilla::Atomic mElements[kLength]; + mozilla::UniquePtr mNext; + + ListChunk() : mNext(nullptr) {} + }; + + ListChunk mList; + mozilla::Atomic mLength; + +public: + ChunkedList() : mLength(0) {} + + ~ChunkedList() { + // There can be writes happening after this destructor runs, so keep + // the list contents and don't reset mLength. But if there are more + // elements left than the first chunk can hold, then all hell breaks + // loose for any write that would happen after that because any extra + // chunk would be deallocated, so just crash in that case. + MOZ_RELEASE_ASSERT(mLength <= ListChunk::kLength); + } + + // Add an element at the end of the last chunk of the list. Create a new + // chunk if there is not enough room. + // This is not thread-safe with another thread calling Add or Remove. + void Add(T aValue) + { + ListChunk *list = &mList; + size_t position = mLength; + for (; position >= ListChunk::kLength; position -= ListChunk::kLength) { + if (!list->mNext) { + list->mNext.reset(new ListChunk()); + } + list = list->mNext.get(); + } + // Use an order of operations that ensures any racing Contains call + // can't be hurt. + list->mElements[position] = aValue; + mLength++; + } + + // Remove an element from the list by replacing it with the last element + // of the list, and then shrinking the list. + // This is not thread-safe with another thread calling Add or Remove. + void Remove(T aValue) + { + if (!mLength) { + return; + } + ListChunk *list = &mList; + size_t last = mLength - 1; + do { + size_t position = 0; + // Look for an element matching the given value. + for (; position < ListChunk::kLength; position++) { + if (aValue == list->mElements[position]) { + ListChunk *last_list = list; + // Look for the last element in the list, starting from where we are + // instead of starting over. + for (; last >= ListChunk::kLength; last -= ListChunk::kLength) { + last_list = last_list->mNext.get(); + } + // Use an order of operations that ensures any racing Contains call + // can't be hurt. + T value = last_list->mElements[last]; + list->mElements[position] = value; + mLength--; + return; + } + } + last -= ListChunk::kLength; + list = list->mNext.get(); + } while (list); + } + + // Returns whether the list contains the given value. It is meant to be safe + // to use without locking, with the tradeoff of being not entirely accurate + // if another thread adds or removes an element while this function runs. + bool Contains(T aValue) + { + ListChunk *list = &mList; + // Fix the range of the lookup to whatever the list length is when the + // function is called. + size_t length = mLength; + do { + size_t list_length = ListChunk::kLength; + list_length = std::min(list_length, length); + for (size_t position = 0; position < list_length; position++) { + if (aValue == list->mElements[position]) { + return true; + } + } + length -= ListChunk::kLength; + list = list->mNext.get(); + } while (list); + + return false; + } +}; + +typedef ChunkedList FdList; + +// Return a list used to hold the IDs of the current debug files. On unix // an ID is a file descriptor. On Windows it is a file HANDLE. -std::vector* +FdList& getDebugFileIDs() { - PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(DebugFilesAutoLock::getDebugFileIDsLock()); - // We have to use new as some write happen during static destructors - // so an static std::vector might be destroyed while we still need it. - static std::vector* DebugFileIDs = new std::vector(); + static FdList DebugFileIDs; return DebugFileIDs; } + } // anonymous namespace namespace mozilla { @@ -96,40 +215,26 @@ bool IsDebugFile(intptr_t aFileID) { - DebugFilesAutoLock lockedScope; - - std::vector& Vec = *getDebugFileIDs(); - return std::find(Vec.begin(), Vec.end(), aFileID) != Vec.end(); + return getDebugFileIDs().Contains(aFileID); } -// Clean-up for the registered debug files. -// We should probably make sure all debug files are unregistered instead. -// But as the poison IO interposer is used for late-write checks we're not -// disabling it at any point yet. So Really no need for this. -// -// void ClearDebugFileRegister() { -// PRLock *Lock; -// { -// DebugFilesAutoLock lockedScope; -// delete getDebugFileIDs(); -// Lock = DebugFilesAutoLock::getDebugFileIDsLock(); -// DebugFilesAutoLock::Clear(); -// } -// PR_DestroyLock(Lock); -// } - } // namespace mozilla extern "C" { void -MozillaRegisterDebugFD(int aFd) +MozillaRegisterDebugHandle(intptr_t aHandle) { - intptr_t fileId = FileDescriptorToID(aFd); DebugFilesAutoLock lockedScope; - std::vector& Vec = *getDebugFileIDs(); - MOZ_ASSERT(std::find(Vec.begin(), Vec.end(), fileId) == Vec.end()); - Vec.push_back(fileId); + FdList& DebugFileIDs = getDebugFileIDs(); + MOZ_ASSERT(!DebugFileIDs.Contains(aHandle)); + DebugFileIDs.Add(aHandle); +} + +void +MozillaRegisterDebugFD(int aFd) +{ + MozillaRegisterDebugHandle(FileDescriptorToHandle(aFd)); } void @@ -143,15 +248,18 @@ } void -MozillaUnRegisterDebugFD(int aFd) +MozillaUnRegisterDebugHandle(intptr_t aHandle) { DebugFilesAutoLock lockedScope; - intptr_t fileId = FileDescriptorToID(aFd); - std::vector& Vec = *getDebugFileIDs(); - std::vector::iterator i = - std::find(Vec.begin(), Vec.end(), fileId); - MOZ_ASSERT(i != Vec.end()); - Vec.erase(i); + FdList& DebugFileIDs = getDebugFileIDs(); + MOZ_ASSERT(DebugFileIDs.Contains(aHandle)); + DebugFileIDs.Remove(aHandle); +} + +void +MozillaUnRegisterDebugFD(int aFd) +{ + MozillaUnRegisterDebugHandle(FileDescriptorToHandle(aFd)); } void @@ -166,3 +274,17 @@ } } // extern "C" + +#ifdef MOZ_REPLACE_MALLOC +void +DebugFdRegistry::RegisterHandle(intptr_t aHandle) +{ + MozillaRegisterDebugHandle(aHandle); +} + +void +DebugFdRegistry::UnRegisterHandle(intptr_t aHandle) +{ + MozillaUnRegisterDebugHandle(aHandle); +} +#endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposer.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposer.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposer.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposer.h 2014-11-26 21:46:07.000000000 +0000 @@ -12,12 +12,22 @@ MOZ_BEGIN_EXTERN_C +/** Register file handle to be ignored by poisoning IO interposer. This function + * and the corresponding UnRegister function are necessary for exchange of handles + * between binaries not using the same CRT on Windows (which happens when one of + * them links the static CRT). In such cases, giving file descriptors or FILEs + * doesn't work because _get_osfhandle fails with "invalid parameter". */ +void MozillaRegisterDebugHandle(intptr_t aHandle); + /** Register file descriptor to be ignored by poisoning IO interposer */ void MozillaRegisterDebugFD(int aFd); /** Register file to be ignored by poisoning IO interposer */ void MozillaRegisterDebugFILE(FILE* aFile); +/** Unregister file handle from being ignored by poisoning IO interposer */ +void MozillaUnRegisterDebugHandle(intptr_t aHandle); + /** Unregister file descriptor from being ignored by poisoning IO interposer */ void MozillaUnRegisterDebugFD(int aFd); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposerMac.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposerMac.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposerMac.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposerMac.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -32,6 +32,10 @@ #include #include +#ifdef MOZ_REPLACE_MALLOC +#include "replace_malloc_bridge.h" +#endif + namespace { using namespace mozilla; @@ -342,6 +346,14 @@ MozillaRegisterDebugFD(1); MozillaRegisterDebugFD(2); +#ifdef MOZ_REPLACE_MALLOC + // The contract with InitDebugFd is that the given registry can be used + // at any moment, so the instance needs to persist longer than the scope + // of this functions. + static DebugFdRegistry registry; + ReplaceMalloc::InitDebugFd(registry); +#endif + for (int i = 0; i < NumFunctions; ++i) { FuncData* d = Functions[i]; if (!d->Function) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposerWin.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposerWin.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/build/PoisonIOInterposerWin.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/build/PoisonIOInterposerWin.cpp 2014-11-26 21:46:07.000000000 +0000 @@ -23,6 +23,10 @@ #include "nsWindowsDllInterceptor.h" #include "plstr.h" +#ifdef MOZ_REPLACE_MALLOC +#include "replace_malloc_bridge.h" +#endif + using namespace mozilla; namespace { @@ -443,6 +447,14 @@ MozillaRegisterDebugFD(1); MozillaRegisterDebugFD(2); +#ifdef MOZ_REPLACE_MALLOC + // The contract with InitDebugFd is that the given registry can be used + // at any moment, so the instance needs to persist longer than the scope + // of this functions. + static DebugFdRegistry registry; + ReplaceMalloc::InitDebugFd(registry); +#endif + // Initialize dll interceptor and add hooks sNtDllInterceptor.Init("ntdll.dll"); sNtDllInterceptor.AddHook( diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/ds/TimeStamp.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/ds/TimeStamp.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/ds/TimeStamp.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/ds/TimeStamp.h 2014-11-26 21:46:07.000000000 +0000 @@ -387,11 +387,20 @@ MOZ_CONSTEXPR TimeStamp() : mValue(0) {} // Default copy-constructor and assignment are OK -#ifdef MOZ_WIDGET_GONK - TimeStamp(int64_t aAndroidTime) : mValue(aAndroidTime) + /** + * The system timestamps are the same as the TimeStamp + * retrieved by mozilla::TimeStamp. Since we need this for + * vsync timestamps, we enable the creation of mozilla::TimeStamps + * on platforms that support vsync aligned refresh drivers / compositors + * Verified true as of Nov 7, 2014: B2G and OS X + * UNTESTED ON OTHER PLATFORMS + */ +#if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_COCOA) + static TimeStamp FromSystemTime(int64_t aSystemTime) { - static_assert(sizeof(aAndroidTime) == sizeof(TimeStampValue), - "Android timestamp should be same units as TimeStampValue"); + static_assert(sizeof(aSystemTime) == sizeof(TimeStampValue), + "System timestamp should be same units as TimeStampValue"); + return TimeStamp(aSystemTime); } #endif @@ -508,17 +517,13 @@ } bool operator==(const TimeStamp& aOther) const { - // Maybe it's ok to check == with null timestamps? - MOZ_ASSERT(!IsNull() && "Cannot compute with a null value"); - MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value"); - return mValue == aOther.mValue; + return IsNull() + ? aOther.IsNull() + : !aOther.IsNull() && mValue == aOther.mValue; } bool operator!=(const TimeStamp& aOther) const { - // Maybe it's ok to check != with null timestamps? - MOZ_ASSERT(!IsNull(), "Cannot compute with a null value"); - MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value"); - return mValue != aOther.mValue; + return !(*this == aOther); } // Comparing TimeStamps for equality should be discouraged. Adding diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/glue/nsCycleCollectionParticipant.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/glue/nsCycleCollectionParticipant.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/glue/nsCycleCollectionParticipant.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/glue/nsCycleCollectionParticipant.h 2014-11-26 21:46:08.000000000 +0000 @@ -713,6 +713,29 @@ }; \ static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_NATIVE_CLASS(_class) \ + void DeleteCycleCollectable(void) \ + { \ + delete this; \ + } \ + class NS_CYCLE_COLLECTION_INNERCLASS \ + : public nsCycleCollectionParticipant \ + { \ + public: \ + MOZ_CONSTEXPR NS_CYCLE_COLLECTION_INNERCLASS () \ + : nsCycleCollectionParticipant(true) {} \ + private: \ + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \ + NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \ + NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \ + NS_IMETHOD_(bool) CanSkipThisReal(void *p); \ + static nsCycleCollectionParticipant* GetParticipant() \ + { \ + return &_class::NS_CYCLE_COLLECTION_INNERNAME; \ + } \ + }; \ + static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; + #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_NATIVE_CLASS_WITH_CUSTOM_DELETE(_class) \ class NS_CYCLE_COLLECTION_INNERCLASS \ : public nsCycleCollectionParticipant \ diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/glue/nsTArray.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/glue/nsTArray.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/glue/nsTArray.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/glue/nsTArray.h 2014-11-26 21:46:08.000000000 +0000 @@ -2003,6 +2003,13 @@ { } + template + self_type& operator=(const nsTArray_Impl& other) + { + Base::operator=(other); + return *this; + } + operator const AutoFallibleTArray&() const { return *reinterpret_cast*>(this); @@ -2033,6 +2040,13 @@ { } + template + self_type& operator=(const nsTArray_Impl& other) + { + Base::operator=(other); + return *this; + } + operator const nsAutoTArray&() const { return *reinterpret_cast*>(this); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/glue/pldhash.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/glue/pldhash.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/glue/pldhash.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/glue/pldhash.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -707,7 +707,7 @@ uint32_t i = 0; bool didRemove = false; - if (ChaosMode::isActive()) { + if (ChaosMode::isActive(ChaosMode::HashTableIteration)) { // Start iterating at a random point in the hashtable. It would be // even more chaotic to iterate in fully random order, but that's a lot // more work. @@ -855,7 +855,7 @@ uint32_t tableSize = capacity * mTable->EntrySize(); char* entryLimit = mEntryAddr + tableSize; - if (ChaosMode::isActive()) { + if (ChaosMode::isActive(ChaosMode::HashTableIteration)) { // Start iterating at a random point in the hashtable. It would be // even more chaotic to iterate in fully random order, but that's a lot // more work. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/idl-parser/header.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/idl-parser/header.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/idl-parser/header.py 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/idl-parser/header.py 2014-11-26 21:46:08.000000000 +0000 @@ -400,6 +400,8 @@ for member in iface.members: if isinstance(member, xpidl.Attribute): + if member.infallible: + fd.write("\\\n using %s::%s; " % (iface.name, attributeNativeName(member, True))) fd.write("\\\n %s MOZ_OVERRIDE; " % attributeAsNative(member, True)) if not member.readonly: fd.write("\\\n %s MOZ_OVERRIDE; " % attributeAsNative(member, False)) @@ -412,11 +414,13 @@ fd.write(iface_forward % names) - def emitTemplate(tmpl, tmpl_notxpcom=None): + def emitTemplate(forward_infallible, tmpl, tmpl_notxpcom=None): if tmpl_notxpcom == None: tmpl_notxpcom = tmpl for member in iface.members: if isinstance(member, xpidl.Attribute): + if forward_infallible and member.infallible: + fd.write("\\\n using %s::%s; " % (iface.name, attributeNativeName(member, True))) fd.write(tmpl % {'asNative': attributeAsNative(member, True), 'nativeName': attributeNativeName(member, True), 'paramList': attributeParamNames(member)}) @@ -438,14 +442,16 @@ elif not member.kind in ('attribute', 'method'): fd.write('\\') - emitTemplate("\\\n %(asNative)s MOZ_OVERRIDE { return _to %(nativeName)s(%(paramList)s); } ") + emitTemplate(True, + "\\\n %(asNative)s MOZ_OVERRIDE { return _to %(nativeName)s(%(paramList)s); } ") fd.write(iface_forward_safe % names) # Don't try to safely forward notxpcom functions, because we have no # sensible default error return. Instead, the caller will have to # implement them. - emitTemplate("\\\n %(asNative)s MOZ_OVERRIDE { return !_to ? NS_ERROR_NULL_POINTER : _to->%(nativeName)s(%(paramList)s); } ", + emitTemplate(False, + "\\\n %(asNative)s MOZ_OVERRIDE { return !_to ? NS_ERROR_NULL_POINTER : _to->%(nativeName)s(%(paramList)s); } ", "\\\n %(asNative)s MOZ_OVERRIDE; ") fd.write(iface_template_prolog % names) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/io/FileUtilsWin.h thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/io/FileUtilsWin.h --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/io/FileUtilsWin.h 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/io/FileUtilsWin.h 2014-11-26 21:46:08.000000000 +0000 @@ -21,7 +21,7 @@ auto inputPath = PromiseFlatString(aDosPath); // Try to get the long path, or else get the required length of the long path DWORD longPathLen = GetLongPathNameW(inputPath.get(), - aDosPath.BeginWriting(), + reinterpret_cast(aDosPath.BeginWriting()), aDosPathOriginalLen); if (longPathLen == 0) { return false; @@ -33,7 +33,7 @@ } // Now we have a large enough buffer, get the actual string longPathLen = GetLongPathNameW(inputPath.get(), - aDosPath.BeginWriting(), aDosPath.Length()); + reinterpret_cast(aDosPath.BeginWriting()), aDosPath.Length()); if (longPathLen == 0) { return false; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/io/nsLocalFileUnix.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/io/nsLocalFileUnix.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/io/nsLocalFileUnix.cpp 2014-11-14 09:37:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/io/nsLocalFileUnix.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -11,6 +11,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" +#include #include #include #include @@ -1407,10 +1408,9 @@ #endif && dq.dqb_bhardlimit) { int64_t QuotaSpaceAvailable = 0; - if (dq.dqb_bhardlimit > dq.dqb_curspace) { - QuotaSpaceAvailable = - int64_t(fs_buf.F_BSIZE * (dq.dqb_bhardlimit - dq.dqb_curspace)); - } + // dqb_bhardlimit is count of BLOCK_SIZE blocks, dqb_curspace is bytes + if ((BLOCK_SIZE * dq.dqb_bhardlimit) > dq.dqb_curspace) + QuotaSpaceAvailable = int64_t(BLOCK_SIZE * dq.dqb_bhardlimit - dq.dqb_curspace); if (QuotaSpaceAvailable < *aDiskSpaceAvailable) { *aDiskSpaceAvailable = QuotaSpaceAvailable; } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/tests/moz.build thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/tests/moz.build --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/tests/moz.build 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/tests/moz.build 2014-11-26 21:46:08.000000000 +0000 @@ -122,8 +122,3 @@ RESOURCE_FILES += [ 'test.properties', ] - -if CONFIG['MOZ_DMD']: - USE_LIBS += [ - 'dmd' - ] diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/tests/TestDeadlockDetectorScalability.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/tests/TestDeadlockDetectorScalability.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/tests/TestDeadlockDetectorScalability.cpp 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/tests/TestDeadlockDetectorScalability.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -4,6 +4,9 @@ * 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/. */ +// Avoid DMD-specific parts of MOZ_DEFINE_MALLOC_SIZE_OF +#undef MOZ_DMD + #include "TestHarness.h" #include "nsIMemoryReporter.h" diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/nsEventQueue.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/nsEventQueue.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/nsEventQueue.cpp 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/nsEventQueue.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -90,7 +90,7 @@ // Avoid calling AddRef+Release while holding our monitor. nsRefPtr event(aRunnable); - if (ChaosMode::isActive()) { + if (ChaosMode::isActive(ChaosMode::ThreadScheduling)) { // With probability 0.5, yield so other threads have a chance to // dispatch events to this queue first. if (ChaosMode::randomUint32LessThan(2)) { diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/nsThread.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/nsThread.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/nsThread.cpp 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/nsThread.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -285,7 +285,7 @@ static void SetupCurrentThreadForChaosMode() { - if (!ChaosMode::isActive()) { + if (!ChaosMode::isActive(ChaosMode::ThreadScheduling)) { return; } @@ -888,7 +888,7 @@ pri = PR_PRIORITY_NORMAL; } // If chaos mode is active, retain the randomly chosen priority - if (!ChaosMode::isActive()) { + if (!ChaosMode::isActive(ChaosMode::ThreadScheduling)) { PR_SetThreadPriority(mThread, pri); } diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/nsTimerImpl.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/nsTimerImpl.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/nsTimerImpl.cpp 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/nsTimerImpl.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -13,6 +13,9 @@ #include "pratom.h" #include "GeckoProfiler.h" #include "mozilla/Atomics.h" +#ifdef MOZ_NUWA_PROCESS +#include "ipc/Nuwa.h" +#endif using mozilla::Atomic; using mozilla::TimeDuration; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/ThreadStackHelper.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/ThreadStackHelper.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/ThreadStackHelper.cpp 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/ThreadStackHelper.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -38,6 +38,10 @@ #include "processor/stackwalker_arm.h" #endif +#if defined(MOZ_VALGRIND) +# include +#endif + #include #include @@ -260,6 +264,14 @@ MOZ_ALWAYS_TRUE(::ResumeThread(mThreadID) != DWORD(-1)); #elif defined(XP_MACOSX) +# if defined(MOZ_VALGRIND) && defined(RUNNING_ON_VALGRIND) + if (RUNNING_ON_VALGRIND) { + /* thread_suspend and thread_resume sometimes hang runs on Valgrind, + for unknown reasons. So, just avoid them. See bug 1100911. */ + return; + } +# endif + if (::thread_suspend(mThreadID) != KERN_SUCCESS) { MOZ_ASSERT(false); return; diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/TimerThread.cpp thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/TimerThread.cpp --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xpcom/threads/TimerThread.cpp 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xpcom/threads/TimerThread.cpp 2014-11-26 21:46:08.000000000 +0000 @@ -237,7 +237,7 @@ if (mSleeping) { // Sleep for 0.1 seconds while not firing timers. uint32_t milliseconds = 100; - if (ChaosMode::isActive()) { + if (ChaosMode::isActive(ChaosMode::TimerScheduling)) { milliseconds = ChaosMode::randomUint32LessThan(200); } waitFor = PR_MillisecondsToInterval(milliseconds); @@ -324,7 +324,7 @@ // interval is so small we should not wait at all). double microseconds = (timeout - now).ToMilliseconds() * 1000; - if (ChaosMode::isActive()) { + if (ChaosMode::isActive(ChaosMode::TimerScheduling)) { // The mean value of sFractions must be 1 to ensure that // the average of a long sequence of timeouts converges to the // actual sum of their times. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xulrunner/app/install_app.py thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xulrunner/app/install_app.py --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/mozilla/xulrunner/app/install_app.py 2014-11-14 09:37:40.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/mozilla/xulrunner/app/install_app.py 2014-11-26 21:46:08.000000000 +0000 @@ -38,7 +38,7 @@ return leafName + ".exe" elif sys.platform == "darwin": - xulrunnerStubName = "xulrunner" + xulrunnerStubName = "xulrunner-stub" def installApp(appLocation, installDir, appName, greDir): zipApp, iniparser, appName = validateArguments(appLocation, installDir, appName, greDir) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/browser/browser-prefs.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/browser/browser-prefs.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/browser/browser-prefs.js 2014-11-14 09:36:41.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/browser/browser-prefs.js 2014-11-26 21:45:01.000000000 +0000 @@ -718,6 +718,8 @@ pref("privacy.sanitize.sanitizeOnShutdown", false); pref("privacy.sanitize.promptOnSanitize", true); +pref("privacy.warn_tracking_content", true); + // Show XUL error pages instead of alerts for errors pref("browser.xul.error_pages.enabled", true); pref("browser.xul.error_pages.expert_bad_cert", false); @@ -948,6 +950,7 @@ pref("services.sync.prefs.sync.privacy.sanitize.promptOnSanitize", true); pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true); pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true); +pref("services.sync.prefs.sync.privacy.warn_tracking_content", true); pref("services.sync.prefs.sync.security.OCSP.enabled", true); pref("services.sync.prefs.sync.security.OCSP.require", true); pref("services.sync.prefs.sync.security.default_personal_cert", true); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/common/bindings/notification.xml thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/common/bindings/notification.xml --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/common/bindings/notification.xml 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/common/bindings/notification.xml 2014-11-26 21:44:57.000000000 +0000 @@ -90,7 +90,6 @@ { + const nsIPermissionManager = Components.interfaces.nsIPermissionManager; + Components.classes["@mozilla.org/permissionmanager;1"] + .getService(nsIPermissionManager) + .add(this.activeBrowser.currentURI, + "trackingprotection", + nsIPermissionManager.ALLOW_ACTION); + this.reloadPage(); + } + }]; + } } else if (aState & nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT && this._prefs.getBoolPref("security.warn_mixed_display_content")) { pref = "security.warn_mixed_display_content"; @@ -195,7 +227,7 @@ label: this._stringBundle.GetStringFromName("SecurityPreferences.label"), accessKey: this._stringBundle.GetStringFromName("SecurityPreferences.accesskey"), callback: function() { - goPreferences("ssl_pane"); + goPreferences(pane); return true; } }); @@ -374,31 +406,31 @@ case "addon-install-blocked": var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - if (installInfo.originator.top == browser.contentWindow) + if (installInfo.browser == browser) this.addonInstallBlocked(installInfo); break; case "addon-install-complete": var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - if (installInfo.originator.top == browser.contentWindow) + if (installInfo.browser == browser) this.addonInstallComplete(installInfo); break; case "addon-install-disabled": var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - if (installInfo.originator.top == browser.contentWindow) + if (installInfo.browser == browser) this.addonInstallDisabled(installInfo); break; case "addon-install-failed": var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - if (installInfo.originator.top == browser.contentWindow) + if (installInfo.browser == browser) this.addonInstallFailed(installInfo); break; case "addon-install-started": var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - if (installInfo.originator.top == browser.contentWindow) + if (installInfo.browser == browser) this.addonInstallStarted(installInfo); break; @@ -508,11 +540,6 @@ - null - - null false @@ -572,10 +599,6 @@ - - - - - - - - - - - - + @@ -50,6 +54,11 @@ label="&trackProtect.label;" accesskey="&trackProtect.accesskey;" preference="privacy.trackingprotection.enabled"/> + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/common/src/nsSuiteGlue.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/common/src/nsSuiteGlue.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/common/src/nsSuiteGlue.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/common/src/nsSuiteGlue.js 2014-11-26 21:44:57.000000000 +0000 @@ -678,7 +678,7 @@ { const NS_SHELLSERVICE_CID = "@mozilla.org/suite/shell-service;1"; if (NS_SHELLSERVICE_CID in Components.classes) try { - const nsIShellService = Components.interfaces.nsIShellService; + var nsIShellService = Components.interfaces.nsIShellService; var shellService = Components.classes[NS_SHELLSERVICE_CID] .getService(nsIShellService); diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/installer/Makefile.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/installer/Makefile.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/installer/Makefile.in 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/installer/Makefile.in 2014-11-26 21:44:57.000000000 +0000 @@ -157,6 +157,13 @@ endif DEFINES += -DBINPATH=$(BINPATH) +ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) +RESPATH = $(_APPNAME)/Contents/Resources +else +RESPATH = $(BINPATH) +endif +DEFINES += -DRESPATH=$(RESPATH) + AB = $(firstword $(subst -, ,$(AB_CD))) DEFINES += -DAB=$(AB) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/installer/package-manifest.in thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/installer/package-manifest.in --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/installer/package-manifest.in 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/installer/package-manifest.in 2014-11-26 21:44:57.000000000 +0000 @@ -13,6 +13,19 @@ ; ; file comment ; +; Due to Apple Mac OS X packaging requirements, files that are in the same +; directory on other platforms must be located in different directories on +; Mac OS X. The following defines allow specifying the Mac OS X bundle +; location which also work on other platforms. +; +; @BINPATH@ +; Equals Contents/MacOS/ on Mac OS X and is the path to the main binary on other +; platforms. +; +; @RESPATH@ +; Equals Contents/Resources/ on Mac OS X and is equivalent to @BINPATH@ on other +; platforms. + #filter substitution #ifdef XP_UNIX @@ -25,54 +38,42 @@ ; Mac bundle stuff @APPNAME@/Contents/Info.plist @APPNAME@/Contents/PkgInfo -@APPNAME@/Contents/Resources/seamonkey.icns -@APPNAME@/Contents/Resources/@AB@.lproj/* +@RESPATH@/seamonkey.icns +@RESPATH@/@AB@.lproj/* #endif [@AB_CD@] -@BINPATH@/chrome/@AB_CD@@JAREXT@ -@BINPATH@/chrome/@AB_CD@.manifest -@BINPATH@/defaults/messenger/mailViews.dat -@BINPATH@/defaults/profile/bookmarks.html -@BINPATH@/defaults/profile/chrome/* -@BINPATH@/defaults/profile/mimeTypes.rdf -@BINPATH@/defaults/profile/panels.rdf -@BINPATH@/dictionaries/* -@BINPATH@/hyphenation/* -@BINPATH@/@PREF_DIR@/suite-l10n.js -@BINPATH@/searchplugins/* +@RESPATH@/chrome/@AB_CD@@JAREXT@ +@RESPATH@/chrome/@AB_CD@.manifest +@RESPATH@/defaults/messenger/mailViews.dat +@RESPATH@/defaults/profile/bookmarks.html +@RESPATH@/defaults/profile/chrome/* +@RESPATH@/defaults/profile/mimeTypes.rdf +@RESPATH@/defaults/profile/panels.rdf +@RESPATH@/dictionaries/* +@RESPATH@/hyphenation/* +@RESPATH@/@PREF_DIR@/suite-l10n.js +@RESPATH@/searchplugins/* #ifdef XP_WIN32 @BINPATH@/uninstall/helper.exe #endif #ifdef MOZ_UPDATER -@BINPATH@/update.locale -@BINPATH@/updater.ini +@RESPATH@/update.locale +@RESPATH@/updater.ini #endif [xpcom] -@BINPATH@/dependentlibs.list +@RESPATH@/dependentlibs.list #ifdef GKMEDIAS_SHARED_LIBRARY @BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@ #endif -#ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@DLL_PREFIX@mozalloc@DLL_SUFFIX@ -#else @BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@ -#endif #ifdef MOZ_SHARED_MOZGLUE -#ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@DLL_PREFIX@mozglue@DLL_SUFFIX@ -#else @BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@ #endif -#endif #ifndef MOZ_STATIC_JS -#ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@DLL_PREFIX@mozjs@DLL_SUFFIX@ -#else @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@ #endif -#endif #ifndef MOZ_NATIVE_NSPR #ifndef MOZ_FOLD_LIBS @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@ @@ -81,13 +82,13 @@ #endif #endif #ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/XUL +@BINPATH@/XUL #else @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@ #endif #ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@MOZ_CHILD_PROCESS_NAME@.app/ -@APPNAME@/Contents/MacOS/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@ +@BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/ +@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@ #else @BINPATH@/@MOZ_CHILD_PROCESS_NAME@ #endif @@ -145,531 +146,531 @@ ; [Base Browser Files] #ifdef XP_WIN32 @BINPATH@/@MOZ_APP_NAME@.exe -#elif XP_MACOSX -@APPNAME@/Contents/MacOS/@MOZ_APP_NAME@-bin -@APPNAME@/Contents/MacOS/@MOZ_APP_NAME@ #else @BINPATH@/@MOZ_APP_NAME@-bin @BINPATH@/@MOZ_APP_NAME@ #endif -@BINPATH@/application.ini -@BINPATH@/platform.ini +@RESPATH@/application.ini +@RESPATH@/platform.ini #ifdef MOZ_UPDATER -@BINPATH@/update-settings.ini +@RESPATH@/update-settings.ini #endif #ifndef MOZ_NATIVE_SQLITE #ifndef MOZ_FOLD_LIBS @BINPATH@/@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@ #endif #endif -@BINPATH@/license.txt -@BINPATH@/blocklist.xml +@RESPATH@/license.txt +@RESPATH@/blocklist.xml #ifdef UNIX_BUT_NOT_MAC -@BINPATH@/run-mozilla.sh +@RESPATH@/run-mozilla.sh #endif ; [Components] ; Although components.manifest ends up being shipped inside omni.jar ; it still needs listing here as it is parsed for various binary ; components before being packaged inside omni.jar. -@BINPATH@/components/components.manifest +@RESPATH@/components/components.manifest #ifdef ACCESSIBILITY #ifdef XP_WIN32 @BINPATH@/AccessibleMarshal.dll #endif -@BINPATH@/components/accessibility.xpt +@RESPATH@/components/accessibility.xpt #endif -@BINPATH@/components/alerts.xpt -@BINPATH@/components/appshell.xpt -@BINPATH@/components/appstartup.xpt -@BINPATH@/components/autocomplete.xpt -@BINPATH@/components/autoconfig.xpt -@BINPATH@/components/browser-element.xpt -@BINPATH@/components/caps.xpt -@BINPATH@/components/chrome.xpt -@BINPATH@/components/commandhandler.xpt -@BINPATH@/components/commandlines.xpt -@BINPATH@/components/commuconv.xpt -@BINPATH@/components/composer.xpt -@BINPATH@/components/content_events.xpt -@BINPATH@/components/content_geckomediaplugins.xpt -@BINPATH@/components/content_html.xpt -@BINPATH@/components/content_xslt.xpt -@BINPATH@/components/cookie.xpt +@RESPATH@/components/alerts.xpt +@RESPATH@/components/appshell.xpt +@RESPATH@/components/appstartup.xpt +@RESPATH@/components/autocomplete.xpt +@RESPATH@/components/autoconfig.xpt +@RESPATH@/components/browser-element.xpt +@RESPATH@/components/caps.xpt +@RESPATH@/components/chrome.xpt +@RESPATH@/components/commandhandler.xpt +@RESPATH@/components/commandlines.xpt +@RESPATH@/components/commuconv.xpt +@RESPATH@/components/composer.xpt +@RESPATH@/components/content_events.xpt +@RESPATH@/components/content_geckomediaplugins.xpt +@RESPATH@/components/content_html.xpt +@RESPATH@/components/content_xslt.xpt +@RESPATH@/components/cookie.xpt #ifdef MOZ_ENABLE_DBUS -@BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@ +@RESPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@ #endif -@BINPATH@/components/directory.xpt -@BINPATH@/components/docshell.xpt -@BINPATH@/components/dom.xpt -@BINPATH@/components/dom_alarm.xpt -@BINPATH@/components/dom_apps.xpt -@BINPATH@/components/dom_base.xpt -@BINPATH@/components/dom_canvas.xpt -@BINPATH@/components/dom_core.xpt -@BINPATH@/components/dom_css.xpt -@BINPATH@/components/dom_datastore.xpt -@BINPATH@/components/dom_devicestorage.xpt -@BINPATH@/components/dom_events.xpt +@RESPATH@/components/directory.xpt +@RESPATH@/components/docshell.xpt +@RESPATH@/components/dom.xpt +@RESPATH@/components/dom_alarm.xpt +@RESPATH@/components/dom_apps.xpt +@RESPATH@/components/dom_base.xpt +@RESPATH@/components/dom_canvas.xpt +@RESPATH@/components/dom_core.xpt +@RESPATH@/components/dom_css.xpt +@RESPATH@/components/dom_datastore.xpt +@RESPATH@/components/dom_devicestorage.xpt +@RESPATH@/components/dom_events.xpt #ifdef MOZ_GAMEPAD -@BINPATH@/components/dom_gamepad.xpt +@RESPATH@/components/dom_gamepad.xpt #endif -@BINPATH@/components/dom_geolocation.xpt -@BINPATH@/components/dom_html.xpt -@BINPATH@/components/dom_json.xpt -@BINPATH@/components/dom_media.xpt -@BINPATH@/components/dom_mobilemessage.xpt -@BINPATH@/components/dom_network.xpt -@BINPATH@/components/dom_notification.xpt -@BINPATH@/components/dom_offline.xpt -@BINPATH@/components/dom_permissionsettings.xpt -@BINPATH@/components/dom_power.xpt -@BINPATH@/components/dom_quota.xpt -@BINPATH@/components/dom_range.xpt -@BINPATH@/components/dom_settings.xpt -@BINPATH@/components/dom_sidebar.xpt -@BINPATH@/components/dom_smil.xpt -@BINPATH@/components/dom_storage.xpt -@BINPATH@/components/dom_stylesheets.xpt -@BINPATH@/components/dom_svg.xpt -@BINPATH@/components/dom_system.xpt -@BINPATH@/components/dom_traversal.xpt +@RESPATH@/components/dom_geolocation.xpt +@RESPATH@/components/dom_html.xpt +@RESPATH@/components/dom_json.xpt +@RESPATH@/components/dom_media.xpt +@RESPATH@/components/dom_mobilemessage.xpt +@RESPATH@/components/dom_network.xpt +@RESPATH@/components/dom_notification.xpt +@RESPATH@/components/dom_offline.xpt +@RESPATH@/components/dom_permissionsettings.xpt +@RESPATH@/components/dom_power.xpt +@RESPATH@/components/dom_quota.xpt +@RESPATH@/components/dom_range.xpt +@RESPATH@/components/dom_settings.xpt +@RESPATH@/components/dom_sidebar.xpt +@RESPATH@/components/dom_smil.xpt +@RESPATH@/components/dom_storage.xpt +@RESPATH@/components/dom_stylesheets.xpt +@RESPATH@/components/dom_svg.xpt +@RESPATH@/components/dom_system.xpt +@RESPATH@/components/dom_traversal.xpt #ifdef MOZ_WEBSPEECH -@BINPATH@/components/dom_webspeechrecognition.xpt -@BINPATH@/components/dom_webspeechsynth.xpt +@RESPATH@/components/dom_webspeechrecognition.xpt +@RESPATH@/components/dom_webspeechsynth.xpt #endif -@BINPATH@/components/dom_xbl.xpt -@BINPATH@/components/dom_xpath.xpt -@BINPATH@/components/dom_xul.xpt -@BINPATH@/components/downloads.xpt -@BINPATH@/components/editor.xpt -@BINPATH@/components/embed_base.xpt -@BINPATH@/components/extensions.xpt -@BINPATH@/components/extensions.manifest -@BINPATH@/components/exthandler.xpt -@BINPATH@/components/exthelper.xpt -@BINPATH@/components/fastfind.xpt -@BINPATH@/components/feeds.xpt +@RESPATH@/components/dom_xbl.xpt +@RESPATH@/components/dom_xpath.xpt +@RESPATH@/components/dom_xul.xpt +@RESPATH@/components/downloads.xpt +@RESPATH@/components/editor.xpt +@RESPATH@/components/embed_base.xpt +@RESPATH@/components/extensions.xpt +@RESPATH@/components/extensions.manifest +@RESPATH@/components/exthandler.xpt +@RESPATH@/components/exthelper.xpt +@RESPATH@/components/fastfind.xpt +@RESPATH@/components/feeds.xpt #ifdef MOZ_GTK2 -@BINPATH@/components/filepicker.xpt +@RESPATH@/components/filepicker.xpt #endif -@BINPATH@/components/find.xpt -@BINPATH@/components/gfx.xpt -@BINPATH@/components/html5.xpt -@BINPATH@/components/htmlparser.xpt -@BINPATH@/components/identity.xpt -@BINPATH@/components/imgicon.xpt -@BINPATH@/components/imglib2.xpt -@BINPATH@/components/inspector.xpt -@BINPATH@/components/intl.xpt -@BINPATH@/components/jar.xpt -@BINPATH@/components/jsdebugger.xpt -@BINPATH@/components/jsinspector.xpt -@BINPATH@/components/layout_base.xpt +@RESPATH@/components/find.xpt +@RESPATH@/components/gfx.xpt +@RESPATH@/components/html5.xpt +@RESPATH@/components/htmlparser.xpt +@RESPATH@/components/identity.xpt +@RESPATH@/components/imgicon.xpt +@RESPATH@/components/imglib2.xpt +@RESPATH@/components/inspector.xpt +@RESPATH@/components/intl.xpt +@RESPATH@/components/jar.xpt +@RESPATH@/components/jsdebugger.xpt +@RESPATH@/components/jsinspector.xpt +@RESPATH@/components/layout_base.xpt #ifdef NS_PRINTING -@BINPATH@/components/layout_printing.xpt +@RESPATH@/components/layout_printing.xpt #endif -@BINPATH@/components/layout_xul_tree.xpt -@BINPATH@/components/layout_xul.xpt -@BINPATH@/components/locale.xpt -@BINPATH@/components/loginmgr.xpt -@BINPATH@/components/lwbrk.xpt -@BINPATH@/components/mimetype.xpt -@BINPATH@/components/mozfind.xpt +@RESPATH@/components/layout_xul_tree.xpt +@RESPATH@/components/layout_xul.xpt +@RESPATH@/components/locale.xpt +@RESPATH@/components/loginmgr.xpt +@RESPATH@/components/lwbrk.xpt +@RESPATH@/components/mimetype.xpt +@RESPATH@/components/mozfind.xpt #ifdef MOZ_ENABLE_GNOME_COMPONENT -@BINPATH@/components/@DLL_PREFIX@mozgnome@DLL_SUFFIX@ +@RESPATH@/components/@DLL_PREFIX@mozgnome@DLL_SUFFIX@ #endif -@BINPATH@/components/necko.xpt -@BINPATH@/components/necko_about.xpt -@BINPATH@/components/necko_cache.xpt -@BINPATH@/components/necko_cache2.xpt -@BINPATH@/components/necko_cookie.xpt -@BINPATH@/components/necko_dns.xpt -@BINPATH@/components/necko_file.xpt -@BINPATH@/components/necko_ftp.xpt -@BINPATH@/components/necko_http.xpt -@BINPATH@/components/necko_res.xpt -@BINPATH@/components/necko_socket.xpt -@BINPATH@/components/necko_strconv.xpt -@BINPATH@/components/necko_viewsource.xpt -@BINPATH@/components/necko_websocket.xpt +@RESPATH@/components/necko.xpt +@RESPATH@/components/necko_about.xpt +@RESPATH@/components/necko_cache.xpt +@RESPATH@/components/necko_cache2.xpt +@RESPATH@/components/necko_cookie.xpt +@RESPATH@/components/necko_dns.xpt +@RESPATH@/components/necko_file.xpt +@RESPATH@/components/necko_ftp.xpt +@RESPATH@/components/necko_http.xpt +@RESPATH@/components/necko_res.xpt +@RESPATH@/components/necko_socket.xpt +@RESPATH@/components/necko_strconv.xpt +@RESPATH@/components/necko_viewsource.xpt +@RESPATH@/components/necko_websocket.xpt #ifdef NECKO_WIFI -@BINPATH@/components/necko_wifi.xpt +@RESPATH@/components/necko_wifi.xpt #endif -@BINPATH@/components/necko_wyciwyg.xpt +@RESPATH@/components/necko_wyciwyg.xpt #ifdef MOZ_ENABLE_GNOMEVFS -@BINPATH@/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@ +@RESPATH@/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@ #endif -@BINPATH@/components/parentalcontrols.xpt +@RESPATH@/components/parentalcontrols.xpt #ifdef MOZ_WEBRTC -@BINPATH@/components/peerconnection.xpt +@RESPATH@/components/peerconnection.xpt #endif -@BINPATH@/components/places.xpt -@BINPATH@/components/plugin.xpt -@BINPATH@/components/pref.xpt -@BINPATH@/components/prefetch.xpt -@BINPATH@/components/profile.xpt +@RESPATH@/components/places.xpt +@RESPATH@/components/plugin.xpt +@RESPATH@/components/pref.xpt +@RESPATH@/components/prefetch.xpt +@RESPATH@/components/profile.xpt #ifdef MOZ_ENABLE_PROFILER_SPS -@BINPATH@/components/profiler.xpt +@RESPATH@/components/profiler.xpt #endif -@BINPATH@/components/rdf.xpt -@BINPATH@/components/satchel.xpt -@BINPATH@/components/satchel.manifest -@BINPATH@/components/saxparser.xpt -@BINPATH@/components/services-crypto-component.xpt -@BINPATH@/components/shellservice.xpt -@BINPATH@/components/shistory.xpt -@BINPATH@/components/smile.xpt -@BINPATH@/components/spellchecker.xpt -@BINPATH@/components/startupcache.xpt -@BINPATH@/components/storage.xpt -@BINPATH@/components/@DLL_PREFIX@suite@DLL_SUFFIX@ -@BINPATH@/components/SuiteBrowser.manifest -@BINPATH@/components/suitecommon.xpt -@BINPATH@/components/SuiteCommon.manifest -@BINPATH@/components/suitefeeds.xpt -@BINPATH@/components/SuiteFeeds.manifest -@BINPATH@/components/suitemigration.xpt -@BINPATH@/components/telemetry.xpt -@BINPATH@/components/toolkit_finalizationwitness.xpt -@BINPATH@/components/toolkit_formautofill.xpt -@BINPATH@/components/toolkit_osfile.xpt -@BINPATH@/components/toolkit_xulstore.xpt -@BINPATH@/components/toolkitplaces.manifest -@BINPATH@/components/toolkitprofile.xpt +@RESPATH@/components/rdf.xpt +@RESPATH@/components/satchel.xpt +@RESPATH@/components/satchel.manifest +@RESPATH@/components/saxparser.xpt +@RESPATH@/components/services-crypto-component.xpt +@RESPATH@/components/shellservice.xpt +@RESPATH@/components/shistory.xpt +@RESPATH@/components/smile.xpt +@RESPATH@/components/spellchecker.xpt +@RESPATH@/components/startupcache.xpt +@RESPATH@/components/storage.xpt +@RESPATH@/components/@DLL_PREFIX@suite@DLL_SUFFIX@ +@RESPATH@/components/SuiteBrowser.manifest +@RESPATH@/components/suitecommon.xpt +@RESPATH@/components/SuiteCommon.manifest +@RESPATH@/components/suitefeeds.xpt +@RESPATH@/components/SuiteFeeds.manifest +@RESPATH@/components/suitemigration.xpt +@RESPATH@/components/telemetry.xpt +@RESPATH@/components/toolkit_finalizationwitness.xpt +@RESPATH@/components/toolkit_formautofill.xpt +@RESPATH@/components/toolkit_osfile.xpt +@RESPATH@/components/toolkit_xulstore.xpt +@RESPATH@/components/toolkitplaces.manifest +@RESPATH@/components/toolkitprofile.xpt #ifdef UNIX_BUT_NOT_MAC -@BINPATH@/components/toolkitremote.xpt +@RESPATH@/components/toolkitremote.xpt #endif -@BINPATH@/components/toolkitsearch.manifest -@BINPATH@/components/txmgr.xpt -@BINPATH@/components/txtsvc.xpt -@BINPATH@/components/uconv.xpt -@BINPATH@/components/unicharutil.xpt -@BINPATH@/components/update.xpt -@BINPATH@/components/uriloader.xpt +@RESPATH@/components/toolkitsearch.manifest +@RESPATH@/components/txmgr.xpt +@RESPATH@/components/txtsvc.xpt +@RESPATH@/components/uconv.xpt +@RESPATH@/components/unicharutil.xpt +@RESPATH@/components/update.xpt +@RESPATH@/components/uriloader.xpt #ifdef MOZ_URL_CLASSIFIER -@BINPATH@/components/url-classifier.xpt -#endif -@BINPATH@/components/urlformatter.xpt -@BINPATH@/components/webBrowser_core.xpt -@BINPATH@/components/webbrowserpersist.xpt -@BINPATH@/components/widget.xpt -#ifdef XP_MACOSX -@BINPATH@/components/widget_cocoa.xpt +@RESPATH@/components/url-classifier.xpt #endif -@BINPATH@/components/windowds.xpt -@BINPATH@/components/windowwatcher.xpt -@BINPATH@/components/xpcom_base.xpt -@BINPATH@/components/xpcom_components.xpt -@BINPATH@/components/xpcom_ds.xpt -@BINPATH@/components/xpcom_io.xpt -@BINPATH@/components/xpcom_system.xpt -@BINPATH@/components/xpcom_threads.xpt -@BINPATH@/components/xpcom_xpti.xpt -@BINPATH@/components/xpconnect.xpt -@BINPATH@/components/xulapp.xpt -@BINPATH@/components/xul.xpt -@BINPATH@/components/xultmpl.xpt -@BINPATH@/components/zipwriter.xpt +@RESPATH@/components/urlformatter.xpt +@RESPATH@/components/webBrowser_core.xpt +@RESPATH@/components/webbrowserpersist.xpt +@RESPATH@/components/widget.xpt +#ifdef XP_MACOSX +@RESPATH@/components/widget_cocoa.xpt +#endif +@RESPATH@/components/windowds.xpt +@RESPATH@/components/windowwatcher.xpt +@RESPATH@/components/xpcom_base.xpt +@RESPATH@/components/xpcom_components.xpt +@RESPATH@/components/xpcom_ds.xpt +@RESPATH@/components/xpcom_io.xpt +@RESPATH@/components/xpcom_system.xpt +@RESPATH@/components/xpcom_threads.xpt +@RESPATH@/components/xpcom_xpti.xpt +@RESPATH@/components/xpconnect.xpt +@RESPATH@/components/xulapp.xpt +@RESPATH@/components/xul.xpt +@RESPATH@/components/xultmpl.xpt +@RESPATH@/components/zipwriter.xpt ; JavaScript components -@BINPATH@/components/addonManager.js -@BINPATH@/components/AlarmsManager.js -@BINPATH@/components/AlarmsManager.manifest -@BINPATH@/components/amContentHandler.js -@BINPATH@/components/amInstallTrigger.js -@BINPATH@/components/amWebInstallListener.js -@BINPATH@/components/AppsService.js -@BINPATH@/components/AppsService.manifest -@BINPATH@/components/BrowserElementParent.js -@BINPATH@/components/BrowserElementParent.manifest -@BINPATH@/components/ColorAnalyzer.js -@BINPATH@/components/ConsoleAPIStorage.js -@BINPATH@/components/ConsoleAPI.manifest -@BINPATH@/components/ContactManager.js -@BINPATH@/components/ContactManager.manifest -@BINPATH@/components/contentAreaDropListener.js -@BINPATH@/components/contentAreaDropListener.manifest -@BINPATH@/components/crypto-SDR.js -@BINPATH@/components/cryptoComponents.manifest -@BINPATH@/components/DataStoreImpl.js -@BINPATH@/components/DataStore.manifest -@BINPATH@/components/Downloads.manifest -@BINPATH@/components/DownloadLegacy.js -@BINPATH@/components/FeedConverter.js -@BINPATH@/components/FeedProcessor.js -@BINPATH@/components/FeedProcessor.manifest -@BINPATH@/components/FeedWriter.js -@BINPATH@/components/folderLookupService.js -@BINPATH@/components/formautofill.manifest -@BINPATH@/components/FormAutofillContentService.js -@BINPATH@/components/Identity.manifest -@BINPATH@/components/jsconsole-clhandler.js -@BINPATH@/components/jsconsole-clhandler.manifest -@BINPATH@/components/messageWakeupService.js -@BINPATH@/components/messageWakeupService.manifest -@BINPATH@/components/NetworkGeolocationProvider.js -@BINPATH@/components/NetworkGeolocationProvider.manifest -@BINPATH@/components/nsAbout.js -@BINPATH@/components/nsBlocklistService.js -@BINPATH@/components/nsBrowserContentHandler.js -@BINPATH@/components/nsComposerCmdLineHandler.js -@BINPATH@/components/nsComposerCmdLineHandler.manifest -@BINPATH@/components/nsContentDispatchChooser.js -@BINPATH@/components/nsContentDispatchChooser.manifest -@BINPATH@/components/nsContentPrefService.js -@BINPATH@/components/nsContentPrefService.manifest -@BINPATH@/components/nsDefaultCLH.js -@BINPATH@/components/nsDefaultCLH.manifest -@BINPATH@/components/nsDOMIdentity.js +@RESPATH@/components/addonManager.js +@RESPATH@/components/AlarmsManager.js +@RESPATH@/components/AlarmsManager.manifest +@RESPATH@/components/amContentHandler.js +@RESPATH@/components/amInstallTrigger.js +@RESPATH@/components/amWebInstallListener.js +@RESPATH@/components/AppsService.js +@RESPATH@/components/AppsService.manifest +@RESPATH@/components/BrowserElementParent.js +@RESPATH@/components/BrowserElementParent.manifest +@RESPATH@/components/ColorAnalyzer.js +@RESPATH@/components/ConsoleAPIStorage.js +@RESPATH@/components/ConsoleAPI.manifest +@RESPATH@/components/ContactManager.js +@RESPATH@/components/ContactManager.manifest +@RESPATH@/components/contentAreaDropListener.js +@RESPATH@/components/contentAreaDropListener.manifest +@RESPATH@/components/crypto-SDR.js +@RESPATH@/components/cryptoComponents.manifest +@RESPATH@/components/DataStoreImpl.js +@RESPATH@/components/DataStore.manifest +@RESPATH@/components/Downloads.manifest +@RESPATH@/components/DownloadLegacy.js +@RESPATH@/components/FeedConverter.js +@RESPATH@/components/FeedProcessor.js +@RESPATH@/components/FeedProcessor.manifest +@RESPATH@/components/FeedWriter.js +@RESPATH@/components/folderLookupService.js +@RESPATH@/components/formautofill.manifest +@RESPATH@/components/FormAutofillContentService.js +@RESPATH@/components/Identity.manifest +@RESPATH@/components/jsconsole-clhandler.js +@RESPATH@/components/jsconsole-clhandler.manifest +@RESPATH@/components/messageWakeupService.js +@RESPATH@/components/messageWakeupService.manifest +@RESPATH@/components/NetworkGeolocationProvider.js +@RESPATH@/components/NetworkGeolocationProvider.manifest +@RESPATH@/components/nsAbout.js +@RESPATH@/components/nsBlocklistService.js +@RESPATH@/components/nsBrowserContentHandler.js +@RESPATH@/components/nsComposerCmdLineHandler.js +@RESPATH@/components/nsComposerCmdLineHandler.manifest +@RESPATH@/components/nsContentDispatchChooser.js +@RESPATH@/components/nsContentDispatchChooser.manifest +@RESPATH@/components/nsContentPrefService.js +@RESPATH@/components/nsContentPrefService.manifest +@RESPATH@/components/nsDefaultCLH.js +@RESPATH@/components/nsDefaultCLH.manifest +@RESPATH@/components/nsDOMIdentity.js #ifdef MOZ_GTK2 -@BINPATH@/components/nsFilePicker.js -@BINPATH@/components/nsFilePicker.manifest +@RESPATH@/components/nsFilePicker.js +@RESPATH@/components/nsFilePicker.manifest #endif -@BINPATH@/components/nsFormAutoComplete.js -@BINPATH@/components/nsFormHistory.js -@BINPATH@/components/FormHistoryStartup.js -@BINPATH@/components/nsGopherProtocolStubHandler.js -@BINPATH@/components/nsHandlerService.js -@BINPATH@/components/nsHandlerService.manifest -@BINPATH@/components/nsHelperAppDlg.js -@BINPATH@/components/nsHelperAppDlg.manifest -@BINPATH@/components/nsIDService.js -@BINPATH@/components/nsINIProcessor.js -@BINPATH@/components/nsINIProcessor.manifest -@BINPATH@/components/nsInputListAutoComplete.js -@BINPATH@/components/nsLivemarkService.js -@BINPATH@/components/nsLoginInfo.js -@BINPATH@/components/nsLoginManager.js -@BINPATH@/components/nsLoginManagerPrompter.js -@BINPATH@/components/nsPlacesAutoComplete.js -@BINPATH@/components/nsPlacesAutoComplete.manifest -@BINPATH@/components/nsPlacesExpiration.js -@BINPATH@/components/nsPrompter.js -@BINPATH@/components/nsPrompter.manifest -@BINPATH@/components/nsSearchService.js -@BINPATH@/components/nsSearchSuggestions.js -@BINPATH@/components/nsSessionStartup.js -@BINPATH@/components/nsSessionStore.js -@BINPATH@/components/nsSidebar.js -@BINPATH@/components/nsSuiteDownloadManagerUI.js -@BINPATH@/components/nsSuiteGlue.js -@BINPATH@/components/nsSetDefault.js -@BINPATH@/components/nsSetDefault.manifest -@BINPATH@/components/nsTaggingService.js -@BINPATH@/components/nsTypeAheadFind.js +@RESPATH@/components/nsFormAutoComplete.js +@RESPATH@/components/nsFormHistory.js +@RESPATH@/components/FormHistoryStartup.js +@RESPATH@/components/nsGopherProtocolStubHandler.js +@RESPATH@/components/nsHandlerService.js +@RESPATH@/components/nsHandlerService.manifest +@RESPATH@/components/nsHelperAppDlg.js +@RESPATH@/components/nsHelperAppDlg.manifest +@RESPATH@/components/nsIDService.js +@RESPATH@/components/nsINIProcessor.js +@RESPATH@/components/nsINIProcessor.manifest +@RESPATH@/components/nsInputListAutoComplete.js +@RESPATH@/components/nsLivemarkService.js +@RESPATH@/components/nsLoginInfo.js +@RESPATH@/components/nsLoginManager.js +@RESPATH@/components/nsLoginManagerPrompter.js +@RESPATH@/components/nsPlacesAutoComplete.js +@RESPATH@/components/nsPlacesAutoComplete.manifest +@RESPATH@/components/nsPlacesExpiration.js +@RESPATH@/components/nsPrompter.js +@RESPATH@/components/nsPrompter.manifest +@RESPATH@/components/nsSearchService.js +@RESPATH@/components/nsSearchSuggestions.js +@RESPATH@/components/nsSessionStartup.js +@RESPATH@/components/nsSessionStore.js +@RESPATH@/components/nsSidebar.js +@RESPATH@/components/nsSuiteDownloadManagerUI.js +@RESPATH@/components/nsSuiteGlue.js +@RESPATH@/components/nsSetDefault.js +@RESPATH@/components/nsSetDefault.manifest +@RESPATH@/components/nsTaggingService.js +@RESPATH@/components/nsTypeAheadFind.js #ifdef MOZ_UPDATER -@BINPATH@/components/nsUpdateService.js -@BINPATH@/components/nsUpdateService.manifest -@BINPATH@/components/nsUpdateServiceStub.js +@RESPATH@/components/nsUpdateService.js +@RESPATH@/components/nsUpdateService.manifest +@RESPATH@/components/nsUpdateServiceStub.js #endif -@BINPATH@/components/nsUpdateTimerManager.js -@BINPATH@/components/nsUpdateTimerManager.manifest +@RESPATH@/components/nsUpdateTimerManager.js +@RESPATH@/components/nsUpdateTimerManager.manifest #ifdef MOZ_URL_CLASSIFIER -@BINPATH@/components/nsURLClassifier.manifest -@BINPATH@/components/nsUrlClassifierHashCompleter.js -@BINPATH@/components/nsUrlClassifierLib.js -@BINPATH@/components/nsUrlClassifierListManager.js -#endif -@BINPATH@/components/nsURLFormatter.js -@BINPATH@/components/nsURLFormatter.manifest -@BINPATH@/components/nsWebHandlerApp.js -@BINPATH@/components/nsWebHandlerApp.manifest -@BINPATH@/components/passwordmgr.manifest +@RESPATH@/components/nsURLClassifier.manifest +@RESPATH@/components/nsUrlClassifierHashCompleter.js +@RESPATH@/components/nsUrlClassifierLib.js +@RESPATH@/components/nsUrlClassifierListManager.js +#endif +@RESPATH@/components/nsURLFormatter.js +@RESPATH@/components/nsURLFormatter.manifest +@RESPATH@/components/nsWebHandlerApp.js +@RESPATH@/components/nsWebHandlerApp.manifest +@RESPATH@/components/passwordmgr.manifest #ifdef MOZ_WEBRTC -@BINPATH@/components/PeerConnection.js -@BINPATH@/components/PeerConnection.manifest +@RESPATH@/components/PeerConnection.js +@RESPATH@/components/PeerConnection.manifest #endif -@BINPATH@/components/PermissionSettings.js -@BINPATH@/components/PermissionSettings.manifest -@BINPATH@/components/PhoneNumberService.js -@BINPATH@/components/PhoneNumberService.manifest -@BINPATH@/components/PlacesCategoriesStarter.js -@BINPATH@/components/pluginGlue.manifest -@BINPATH@/components/servicesComponents.manifest -@BINPATH@/components/SettingsManager.js -@BINPATH@/components/SettingsManager.manifest -@BINPATH@/components/SiteSpecificUserAgent.js -@BINPATH@/components/SiteSpecificUserAgent.manifest -@BINPATH@/components/SlowScriptDebug.js -@BINPATH@/components/SlowScriptDebug.manifest -@BINPATH@/components/smileApplication.js -@BINPATH@/components/smileApplication.manifest -@BINPATH@/components/storage-json.js -@BINPATH@/components/SuiteProfileMigrator.js -@BINPATH@/components/SuiteProfileMigrator.manifest +@RESPATH@/components/PermissionSettings.js +@RESPATH@/components/PermissionSettings.manifest +@RESPATH@/components/PhoneNumberService.js +@RESPATH@/components/PhoneNumberService.manifest +@RESPATH@/components/PlacesCategoriesStarter.js +@RESPATH@/components/pluginGlue.manifest +@RESPATH@/components/ProcessSingleton.manifest +@RESPATH@/components/MainProcessSingleton.js +@RESPATH@/components/ContentProcessSingleton.js +@RESPATH@/components/servicesComponents.manifest +@RESPATH@/components/SettingsManager.js +@RESPATH@/components/SettingsManager.manifest +@RESPATH@/components/SiteSpecificUserAgent.js +@RESPATH@/components/SiteSpecificUserAgent.manifest +@RESPATH@/components/SlowScriptDebug.js +@RESPATH@/components/SlowScriptDebug.manifest +@RESPATH@/components/smileApplication.js +@RESPATH@/components/smileApplication.manifest +@RESPATH@/components/storage-json.js +@RESPATH@/components/SuiteProfileMigrator.js +@RESPATH@/components/SuiteProfileMigrator.manifest #ifdef MOZ_SERVICES_SYNC -@BINPATH@/components/SyncComponents.manifest +@RESPATH@/components/SyncComponents.manifest #endif -@BINPATH@/components/TCPSocket.js -@BINPATH@/components/TCPSocket.manifest -@BINPATH@/components/TCPSocketParentIntermediary.js -@BINPATH@/components/txEXSLTRegExFunctions.js -@BINPATH@/components/txEXSLTRegExFunctions.manifest -@BINPATH@/components/UnifiedComplete.manifest -@BINPATH@/components/UnifiedComplete.js +@RESPATH@/components/TCPSocket.js +@RESPATH@/components/TCPSocket.manifest +@RESPATH@/components/TCPSocketParentIntermediary.js +@RESPATH@/components/txEXSLTRegExFunctions.js +@RESPATH@/components/txEXSLTRegExFunctions.manifest +@RESPATH@/components/UnifiedComplete.manifest +@RESPATH@/components/UnifiedComplete.js #ifdef MOZ_SERVICES_SYNC -@BINPATH@/components/Weave.js +@RESPATH@/components/Weave.js #endif -@BINPATH@/components/Webapps.js -@BINPATH@/components/Webapps.manifest -@BINPATH@/components/WebContentConverter.js -@BINPATH@/components/XULStore.js -@BINPATH@/components/XULStore.manifest +@RESPATH@/components/Webapps.js +@RESPATH@/components/Webapps.manifest +@RESPATH@/components/WebContentConverter.js +@RESPATH@/components/XULStore.js +@RESPATH@/components/XULStore.manifest ; Modules -@BINPATH@/modules/* +@RESPATH@/modules/* ; [Browser Chrome Files] -@BINPATH@/chrome/comm@JAREXT@ -@BINPATH@/chrome/comm.manifest -@BINPATH@/chrome/toolkit@JAREXT@ -@BINPATH@/chrome/toolkit.manifest +@RESPATH@/chrome/comm@JAREXT@ +@RESPATH@/chrome/comm.manifest +@RESPATH@/chrome/toolkit@JAREXT@ +@RESPATH@/chrome/toolkit.manifest ; classic theme -@BINPATH@/chrome/classic@JAREXT@ -@BINPATH@/chrome/classic.manifest +@RESPATH@/chrome/classic@JAREXT@ +@RESPATH@/chrome/classic.manifest #ifdef MOZ_OMNIJAR -@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}.xpi +@RESPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}.xpi #else -@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.manifest -@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png -@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf -@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png +@RESPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.manifest +@RESPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png +@RESPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf +@RESPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png #endif ; modern theme #ifdef MOZ_OMNIJAR -@BINPATH@/extensions/modern@themes.mozilla.org.xpi +@RESPATH@/extensions/modern@themes.mozilla.org.xpi #else -@BINPATH@/extensions/modern@themes.mozilla.org/chrome/modern@JAREXT@ -@BINPATH@/extensions/modern@themes.mozilla.org/chrome.manifest -@BINPATH@/extensions/modern@themes.mozilla.org/icon.png -@BINPATH@/extensions/modern@themes.mozilla.org/install.rdf -@BINPATH@/extensions/modern@themes.mozilla.org/preview.png +@RESPATH@/extensions/modern@themes.mozilla.org/chrome/modern@JAREXT@ +@RESPATH@/extensions/modern@themes.mozilla.org/chrome.manifest +@RESPATH@/extensions/modern@themes.mozilla.org/icon.png +@RESPATH@/extensions/modern@themes.mozilla.org/install.rdf +@RESPATH@/extensions/modern@themes.mozilla.org/preview.png #endif ; shell icons #ifdef MOZ_GTK2 -@BINPATH@/chrome/icons/default/bookmarkproperties.png -@BINPATH@/chrome/icons/default/bookmarkproperties16.png -@BINPATH@/chrome/icons/default/bookmarkproperties48.png -@BINPATH@/chrome/icons/default/default.png -@BINPATH@/chrome/icons/default/default16.png -@BINPATH@/chrome/icons/default/default48.png -@BINPATH@/chrome/icons/default/downloadManager.png -@BINPATH@/chrome/icons/default/downloadManager16.png -@BINPATH@/chrome/icons/default/downloadManager48.png -@BINPATH@/chrome/icons/default/editorWindow.png -@BINPATH@/chrome/icons/default/editorWindow16.png -@BINPATH@/chrome/icons/default/editorWindow48.png -@BINPATH@/chrome/icons/default/findBookmarkWindow.png -@BINPATH@/chrome/icons/default/findBookmarkWindow16.png -@BINPATH@/chrome/icons/default/findBookmarkWindow48.png -@BINPATH@/chrome/icons/default/findHistoryWindow.png -@BINPATH@/chrome/icons/default/findHistoryWindow16.png -@BINPATH@/chrome/icons/default/findHistoryWindow48.png -@BINPATH@/chrome/icons/default/history-window.png -@BINPATH@/chrome/icons/default/history-window16.png -@BINPATH@/chrome/icons/default/history-window48.png -@BINPATH@/chrome/icons/default/JSConsoleWindow.png -@BINPATH@/chrome/icons/default/JSConsoleWindow16.png -@BINPATH@/chrome/icons/default/JSConsoleWindow48.png -@BINPATH@/chrome/icons/default/main-window.png -@BINPATH@/chrome/icons/default/main-window16.png -@BINPATH@/chrome/icons/default/main-window48.png -@BINPATH@/chrome/icons/default/places.png -@BINPATH@/chrome/icons/default/places16.png -@BINPATH@/chrome/icons/default/places48.png -@BINPATH@/chrome/icons/default/seamonkey.png +@RESPATH@/chrome/icons/default/bookmarkproperties.png +@RESPATH@/chrome/icons/default/bookmarkproperties16.png +@RESPATH@/chrome/icons/default/bookmarkproperties48.png +@RESPATH@/chrome/icons/default/default.png +@RESPATH@/chrome/icons/default/default16.png +@RESPATH@/chrome/icons/default/default48.png +@RESPATH@/chrome/icons/default/downloadManager.png +@RESPATH@/chrome/icons/default/downloadManager16.png +@RESPATH@/chrome/icons/default/downloadManager48.png +@RESPATH@/chrome/icons/default/editorWindow.png +@RESPATH@/chrome/icons/default/editorWindow16.png +@RESPATH@/chrome/icons/default/editorWindow48.png +@RESPATH@/chrome/icons/default/findBookmarkWindow.png +@RESPATH@/chrome/icons/default/findBookmarkWindow16.png +@RESPATH@/chrome/icons/default/findBookmarkWindow48.png +@RESPATH@/chrome/icons/default/findHistoryWindow.png +@RESPATH@/chrome/icons/default/findHistoryWindow16.png +@RESPATH@/chrome/icons/default/findHistoryWindow48.png +@RESPATH@/chrome/icons/default/history-window.png +@RESPATH@/chrome/icons/default/history-window16.png +@RESPATH@/chrome/icons/default/history-window48.png +@RESPATH@/chrome/icons/default/JSConsoleWindow.png +@RESPATH@/chrome/icons/default/JSConsoleWindow16.png +@RESPATH@/chrome/icons/default/JSConsoleWindow48.png +@RESPATH@/chrome/icons/default/main-window.png +@RESPATH@/chrome/icons/default/main-window16.png +@RESPATH@/chrome/icons/default/main-window48.png +@RESPATH@/chrome/icons/default/places.png +@RESPATH@/chrome/icons/default/places16.png +@RESPATH@/chrome/icons/default/places48.png +@RESPATH@/chrome/icons/default/seamonkey.png #ifdef MOZ_UPDATER -@BINPATH@/icons/updater.png +@RESPATH@/icons/updater.png #endif #elifdef XP_WIN32 -@BINPATH@/chrome/icons/default/bookmarkproperties.ico -@BINPATH@/chrome/icons/default/downloadManager.ico -@BINPATH@/chrome/icons/default/editorWindow.ico -@BINPATH@/chrome/icons/default/findBookmarkWindow.ico -@BINPATH@/chrome/icons/default/findHistoryWindow.ico -@BINPATH@/chrome/icons/default/gif-file.ico -@BINPATH@/chrome/icons/default/history-window.ico -@BINPATH@/chrome/icons/default/html-file.ico -@BINPATH@/chrome/icons/default/image-file.ico -@BINPATH@/chrome/icons/default/jpeg-file.ico -@BINPATH@/chrome/icons/default/JSConsoleWindow.ico -@BINPATH@/chrome/icons/default/main-window.ico -@BINPATH@/chrome/icons/default/misc-file.ico -@BINPATH@/chrome/icons/default/places.ico -@BINPATH@/chrome/icons/default/script-file.ico -@BINPATH@/chrome/icons/default/xml-file.ico -@BINPATH@/chrome/icons/default/xul-file.ico +@RESPATH@/chrome/icons/default/bookmarkproperties.ico +@RESPATH@/chrome/icons/default/downloadManager.ico +@RESPATH@/chrome/icons/default/editorWindow.ico +@RESPATH@/chrome/icons/default/findBookmarkWindow.ico +@RESPATH@/chrome/icons/default/findHistoryWindow.ico +@RESPATH@/chrome/icons/default/gif-file.ico +@RESPATH@/chrome/icons/default/history-window.ico +@RESPATH@/chrome/icons/default/html-file.ico +@RESPATH@/chrome/icons/default/image-file.ico +@RESPATH@/chrome/icons/default/jpeg-file.ico +@RESPATH@/chrome/icons/default/JSConsoleWindow.ico +@RESPATH@/chrome/icons/default/main-window.ico +@RESPATH@/chrome/icons/default/misc-file.ico +@RESPATH@/chrome/icons/default/places.ico +@RESPATH@/chrome/icons/default/script-file.ico +@RESPATH@/chrome/icons/default/xml-file.ico +@RESPATH@/chrome/icons/default/xul-file.ico #endif ; [Default Preferences] ; All the browser/general pref files must be part of base to prevent migration bugs -@BINPATH@/@PREF_DIR@/browser-prefs.js +@RESPATH@/@PREF_DIR@/browser-prefs.js #ifdef LIBXUL_SDK -@BINPATH@/@PREF_DIR@/channel-prefs.js +@RESPATH@/@PREF_DIR@/channel-prefs.js #endif #ifdef MOZ_SERVICES_SYNC -@BINPATH@/@PREF_DIR@/services-sync.js +@RESPATH@/@PREF_DIR@/services-sync.js #endif -@BINPATH@/@PREF_DIR@/composer.js -@BINPATH@/greprefs.js -@BINPATH@/defaults/autoconfig/platform.js -@BINPATH@/defaults/autoconfig/prefcalls.js +@RESPATH@/@PREF_DIR@/composer.js +@RESPATH@/greprefs.js +@RESPATH@/defaults/autoconfig/platform.js +@RESPATH@/defaults/autoconfig/prefcalls.js #ifndef LIBXUL_SDK ; Warning: changing the path to channel-prefs.js can cause bugs. (Bug 756325) -@BINPATH@/defaults/pref/channel-prefs.js +@RESPATH@/defaults/pref/channel-prefs.js #endif ; [Layout Engine Resources] ; Layout debug extension. #ifdef ENABLE_TESTS #ifdef MOZ_DEBUG -@BINPATH@/chrome/layoutdebug@JAREXT@ -@BINPATH@/chrome/layoutdebug.manifest -@BINPATH@/components/layout_debug.xpt +@RESPATH@/chrome/layoutdebug@JAREXT@ +@RESPATH@/chrome/layoutdebug.manifest +@RESPATH@/components/layout_debug.xpt #endif #endif ; Style Sheets, Graphics and other Resources used by the layout engine. -@BINPATH@/res/contenteditable.css -@BINPATH@/res/designmode.css -@BINPATH@/res/EditorOverride.css -@BINPATH@/res/grabber.gif -@BINPATH@/res/langGroups.properties -@BINPATH@/res/language.properties -@BINPATH@/res/svg.css -@BINPATH@/res/table-add-column-after-active.gif -@BINPATH@/res/table-add-column-after-hover.gif -@BINPATH@/res/table-add-column-after.gif -@BINPATH@/res/table-add-column-before-active.gif -@BINPATH@/res/table-add-column-before-hover.gif -@BINPATH@/res/table-add-column-before.gif -@BINPATH@/res/table-add-row-after-active.gif -@BINPATH@/res/table-add-row-after-hover.gif -@BINPATH@/res/table-add-row-after.gif -@BINPATH@/res/table-add-row-before-active.gif -@BINPATH@/res/table-add-row-before-hover.gif -@BINPATH@/res/table-add-row-before.gif -@BINPATH@/res/table-remove-column-active.gif -@BINPATH@/res/table-remove-column-hover.gif -@BINPATH@/res/table-remove-column.gif -@BINPATH@/res/table-remove-row-active.gif -@BINPATH@/res/table-remove-row-hover.gif -@BINPATH@/res/table-remove-row.gif -@BINPATH@/res/ImageDocument.css -@BINPATH@/res/TopLevelImageDocument.css -@BINPATH@/res/TopLevelVideoDocument.css -#ifdef XP_MACOSX -@BINPATH@/res/cursors/* -#endif -@BINPATH@/res/fonts/* -@BINPATH@/res/dtd/* -@BINPATH@/res/html/* -@BINPATH@/res/entityTables/* +@RESPATH@/res/contenteditable.css +@RESPATH@/res/designmode.css +@RESPATH@/res/EditorOverride.css +@RESPATH@/res/grabber.gif +@RESPATH@/res/langGroups.properties +@RESPATH@/res/language.properties +@RESPATH@/res/svg.css +@RESPATH@/res/table-add-column-after-active.gif +@RESPATH@/res/table-add-column-after-hover.gif +@RESPATH@/res/table-add-column-after.gif +@RESPATH@/res/table-add-column-before-active.gif +@RESPATH@/res/table-add-column-before-hover.gif +@RESPATH@/res/table-add-column-before.gif +@RESPATH@/res/table-add-row-after-active.gif +@RESPATH@/res/table-add-row-after-hover.gif +@RESPATH@/res/table-add-row-after.gif +@RESPATH@/res/table-add-row-before-active.gif +@RESPATH@/res/table-add-row-before-hover.gif +@RESPATH@/res/table-add-row-before.gif +@RESPATH@/res/table-remove-column-active.gif +@RESPATH@/res/table-remove-column-hover.gif +@RESPATH@/res/table-remove-column.gif +@RESPATH@/res/table-remove-row-active.gif +@RESPATH@/res/table-remove-row-hover.gif +@RESPATH@/res/table-remove-row.gif +@RESPATH@/res/ImageDocument.css +@RESPATH@/res/TopLevelImageDocument.css +@RESPATH@/res/TopLevelVideoDocument.css +#ifdef XP_MACOSX +@RESPATH@/res/cursors/* +#endif +@RESPATH@/res/fonts/* +@RESPATH@/res/dtd/* +@RESPATH@/res/html/* +@RESPATH@/res/entityTables/* #ifdef XP_MACOSX -@BINPATH@/res/MainMenu.nib/ +@RESPATH@/res/MainMenu.nib/ #endif ; [Personal Security Manager] @@ -678,45 +679,29 @@ ; meaning their .chk files are created there directly. ; #ifndef MOZ_NATIVE_NSS -#ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@DLL_PREFIX@freebl3@DLL_SUFFIX@ -@APPNAME@/Contents/MacOS/@DLL_PREFIX@nss3@DLL_SUFFIX@ -@APPNAME@/Contents/MacOS/@DLL_PREFIX@nssckbi@DLL_SUFFIX@ -#else @BINPATH@/@DLL_PREFIX@freebl3@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@ -#endif #ifndef NSS_DISABLE_DBM -#ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@ -#else @BINPATH@/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@ #endif -#endif #ifndef MOZ_FOLD_LIBS @BINPATH@/@DLL_PREFIX@nssutil3@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@ #endif -#ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/@DLL_PREFIX@softokn3@DLL_SUFFIX@ -#else @BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@ #endif -#endif -@BINPATH@/chrome/pippki@JAREXT@ -@BINPATH@/chrome/pippki.manifest -@BINPATH@/components/pipboot.xpt -@BINPATH@/components/pipnss.xpt -@BINPATH@/components/pippki.xpt +@RESPATH@/chrome/pippki@JAREXT@ +@RESPATH@/chrome/pippki.manifest +@RESPATH@/components/pipboot.xpt +@RESPATH@/components/pipnss.xpt +@RESPATH@/components/pippki.xpt ; For process sandboxing +#if defined(MOZ_SANDBOX) #if defined(XP_WIN) @BINPATH@/@DLL_PREFIX@sandboxbroker@DLL_SUFFIX@ -#elif defined(XP_LINUX) -#if defined(MOZ_CONTENT_SANDBOX) || defined(MOZ_GMP_SANDBOX) -@BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@ #endif #endif @@ -728,16 +713,12 @@ #endif ; LDAP components need to be in the browser for AutoConfig -@BINPATH@/components/mozldap.xpt -@BINPATH@/components/nsLDAPProtocolHandler.js +@RESPATH@/components/mozldap.xpt +@RESPATH@/components/nsLDAPProtocolHandler.js #ifdef XP_WIN32 @BINPATH@/nsldap32v60.dll @BINPATH@/nsldappr32v60.dll @BINPATH@/nsldif32v60.dll -#elif defined(XP_MACOSX) -@APPNAME@/Contents/MacOS/@DLL_PREFIX@ldap60@DLL_SUFFIX@ -@APPNAME@/Contents/MacOS/@DLL_PREFIX@ldif60@DLL_SUFFIX@ -@APPNAME@/Contents/MacOS/@DLL_PREFIX@prldap60@DLL_SUFFIX@ #else @BINPATH@/@DLL_PREFIX@ldap60@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@ldif60@DLL_SUFFIX@ @@ -748,7 +729,7 @@ ; #ifdef MOZ_UPDATER #ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/updater.app/ +@BINPATH@/updater.app/ #else @BINPATH@/updater@BIN_SUFFIX@ #endif @@ -757,19 +738,19 @@ ; [Crash Reporter] ; #ifdef MOZ_CRASHREPORTER -@BINPATH@/components/CrashService.manifest -@BINPATH@/components/CrashService.js -@BINPATH@/components/toolkit_crashservice.xpt +@RESPATH@/components/CrashService.manifest +@RESPATH@/components/CrashService.js +@RESPATH@/components/toolkit_crashservice.xpt #ifdef XP_MACOSX -@APPNAME@/Contents/MacOS/crashreporter.app/ +@BINPATH@/crashreporter.app/ #else @BINPATH@/crashreporter@BIN_SUFFIX@ -@BINPATH@/crashreporter.ini +@RESPATH@/crashreporter.ini #ifdef XP_UNIX -@BINPATH@/Throbber-small.gif +@RESPATH@/Throbber-small.gif #endif #endif -@BINPATH@/crashreporter-override.ini +@RESPATH@/crashreporter-override.ini #ifdef MOZ_CRASHREPORTER_INJECTOR @BINPATH@/breakpadinjector.dll #endif @@ -777,83 +758,83 @@ [mail] ; MailNews component xpts -@BINPATH@/components/addrbook.xpt -@BINPATH@/components/nsAddrbook.manifest -@BINPATH@/components/fts3tok.xpt -@BINPATH@/components/import.xpt -@BINPATH@/components/ldapComponents.manifest -@BINPATH@/components/mailview.xpt -@BINPATH@/components/mime.xpt +@RESPATH@/components/addrbook.xpt +@RESPATH@/components/nsAddrbook.manifest +@RESPATH@/components/fts3tok.xpt +@RESPATH@/components/import.xpt +@RESPATH@/components/ldapComponents.manifest +@RESPATH@/components/mailview.xpt +@RESPATH@/components/mime.xpt #ifdef MOZ_MAPI_SUPPORT -@BINPATH@/components/mapihook.xpt +@RESPATH@/components/mapihook.xpt #endif -@BINPATH@/components/msgbase.xpt -@BINPATH@/components/msgBase.manifest -@BINPATH@/components/msgcompose.xpt -@BINPATH@/components/msgdb.xpt -@BINPATH@/components/msgimap.xpt -@BINPATH@/components/msglocal.xpt -@BINPATH@/components/msgnews.xpt -@BINPATH@/components/msgsearch.xpt -@BINPATH@/components/msgsmime.xpt +@RESPATH@/components/msgbase.xpt +@RESPATH@/components/msgBase.manifest +@RESPATH@/components/msgcompose.xpt +@RESPATH@/components/msgdb.xpt +@RESPATH@/components/msgimap.xpt +@RESPATH@/components/msglocal.xpt +@RESPATH@/components/msgnews.xpt +@RESPATH@/components/msgsearch.xpt +@RESPATH@/components/msgsmime.xpt ; MailNews JS components -@BINPATH@/components/mdn-service.js -@BINPATH@/components/mdn-service.manifest -@BINPATH@/components/mimeJSComponents.js -@BINPATH@/components/msgAsyncPrompter.js -@BINPATH@/components/msgMime.manifest -@BINPATH@/components/newsblog.js -@BINPATH@/components/newsblog.manifest -@BINPATH@/components/nsAbAutoCompleteMyDomain.js -@BINPATH@/components/nsAbAutoCompleteSearch.js -@BINPATH@/components/nsAbLDAPAttributeMap.js -@BINPATH@/components/nsAbLDAPAutoCompleteSearch.js -@BINPATH@/components/nsMailNewsCommandLineHandler.js -@BINPATH@/components/nsMsgTraitService.js -@BINPATH@/components/nsMsgTraitService.manifest -@BINPATH@/components/nsNewsAutoCompleteSearch.js -@BINPATH@/components/nsNewsAutoCompleteSearch.manifest -@BINPATH@/components/nsSMTPProtocolHandler.js -@BINPATH@/components/nsSMTPProtocolHandler.manifest -@BINPATH@/components/offlineStartup.js -@BINPATH@/components/offlineStartup.manifest -@BINPATH@/components/smime-service.js -@BINPATH@/components/smime-service.manifest +@RESPATH@/components/mdn-service.js +@RESPATH@/components/mdn-service.manifest +@RESPATH@/components/mimeJSComponents.js +@RESPATH@/components/msgAsyncPrompter.js +@RESPATH@/components/msgMime.manifest +@RESPATH@/components/newsblog.js +@RESPATH@/components/newsblog.manifest +@RESPATH@/components/nsAbAutoCompleteMyDomain.js +@RESPATH@/components/nsAbAutoCompleteSearch.js +@RESPATH@/components/nsAbLDAPAttributeMap.js +@RESPATH@/components/nsAbLDAPAutoCompleteSearch.js +@RESPATH@/components/nsMailNewsCommandLineHandler.js +@RESPATH@/components/nsMsgTraitService.js +@RESPATH@/components/nsMsgTraitService.manifest +@RESPATH@/components/nsNewsAutoCompleteSearch.js +@RESPATH@/components/nsNewsAutoCompleteSearch.manifest +@RESPATH@/components/nsSMTPProtocolHandler.js +@RESPATH@/components/nsSMTPProtocolHandler.manifest +@RESPATH@/components/offlineStartup.js +@RESPATH@/components/offlineStartup.manifest +@RESPATH@/components/smime-service.js +@RESPATH@/components/smime-service.manifest ; MailNews chrome -@BINPATH@/chrome/messenger@JAREXT@ -@BINPATH@/chrome/messenger.manifest -@BINPATH@/chrome/newsblog@JAREXT@ -@BINPATH@/chrome/newsblog.manifest +@RESPATH@/chrome/messenger@JAREXT@ +@RESPATH@/chrome/messenger.manifest +@RESPATH@/chrome/newsblog@JAREXT@ +@RESPATH@/chrome/newsblog.manifest #ifdef MOZ_GTK2 -@BINPATH@/chrome/icons/default/abcardWindow.png -@BINPATH@/chrome/icons/default/abcardWindow16.png -@BINPATH@/chrome/icons/default/abcardWindow48.png -@BINPATH@/chrome/icons/default/ablistWindow.png -@BINPATH@/chrome/icons/default/ablistWindow16.png -@BINPATH@/chrome/icons/default/ablistWindow48.png -@BINPATH@/chrome/icons/default/addressbookWindow.png -@BINPATH@/chrome/icons/default/addressbookWindow16.png -@BINPATH@/chrome/icons/default/addressbookWindow48.png -@BINPATH@/chrome/icons/default/messengerWindow.png -@BINPATH@/chrome/icons/default/messengerWindow16.png -@BINPATH@/chrome/icons/default/messengerWindow48.png -@BINPATH@/chrome/icons/default/msgcomposeWindow.png -@BINPATH@/chrome/icons/default/msgcomposeWindow16.png -@BINPATH@/chrome/icons/default/msgcomposeWindow48.png +@RESPATH@/chrome/icons/default/abcardWindow.png +@RESPATH@/chrome/icons/default/abcardWindow16.png +@RESPATH@/chrome/icons/default/abcardWindow48.png +@RESPATH@/chrome/icons/default/ablistWindow.png +@RESPATH@/chrome/icons/default/ablistWindow16.png +@RESPATH@/chrome/icons/default/ablistWindow48.png +@RESPATH@/chrome/icons/default/addressbookWindow.png +@RESPATH@/chrome/icons/default/addressbookWindow16.png +@RESPATH@/chrome/icons/default/addressbookWindow48.png +@RESPATH@/chrome/icons/default/messengerWindow.png +@RESPATH@/chrome/icons/default/messengerWindow16.png +@RESPATH@/chrome/icons/default/messengerWindow48.png +@RESPATH@/chrome/icons/default/msgcomposeWindow.png +@RESPATH@/chrome/icons/default/msgcomposeWindow16.png +@RESPATH@/chrome/icons/default/msgcomposeWindow48.png #elifdef XP_WIN32 -@BINPATH@/chrome/icons/default/abcardWindow.ico -@BINPATH@/chrome/icons/default/ablistWindow.ico -@BINPATH@/chrome/icons/default/addressbookWindow.ico -@BINPATH@/chrome/icons/default/messengerWindow.ico -@BINPATH@/chrome/icons/default/msgcomposeWindow.ico +@RESPATH@/chrome/icons/default/abcardWindow.ico +@RESPATH@/chrome/icons/default/ablistWindow.ico +@RESPATH@/chrome/icons/default/addressbookWindow.ico +@RESPATH@/chrome/icons/default/messengerWindow.ico +@RESPATH@/chrome/icons/default/msgcomposeWindow.ico #endif ; [MailNews Default Preferences] -@BINPATH@/@PREF_DIR@/mailnews.js -@BINPATH@/@PREF_DIR@/mdn.js -@BINPATH@/@PREF_DIR@/smime.js +@RESPATH@/@PREF_DIR@/mailnews.js +@RESPATH@/@PREF_DIR@/mdn.js +@RESPATH@/@PREF_DIR@/smime.js #ifdef MOZ_MAPI_SUPPORT @BINPATH@/MapiProxy.dll @@ -861,24 +842,24 @@ #endif #ifdef MOZ_MOVEMAIL -@BINPATH@/isp/movemail.rdf +@RESPATH@/isp/movemail.rdf #endif -@BINPATH@/isp/rss.rdf -@BINPATH@/isp/Bogofilter.sfd -@BINPATH@/isp/DSPAM.sfd -@BINPATH@/isp/POPFile.sfd -@BINPATH@/isp/SpamAssassin.sfd -@BINPATH@/isp/SpamPal.sfd +@RESPATH@/isp/rss.rdf +@RESPATH@/isp/Bogofilter.sfd +@RESPATH@/isp/DSPAM.sfd +@RESPATH@/isp/POPFile.sfd +@RESPATH@/isp/SpamAssassin.sfd +@RESPATH@/isp/SpamPal.sfd ; Gloda -@BINPATH@/chrome/gloda@JAREXT@ -@BINPATH@/chrome/gloda.manifest -@BINPATH@/components/glautocomp.js -@BINPATH@/components/jsmimeemitter.js -@BINPATH@/components/gloda.manifest +@RESPATH@/chrome/gloda@JAREXT@ +@RESPATH@/chrome/gloda.manifest +@RESPATH@/components/glautocomp.js +@RESPATH@/components/jsmimeemitter.js +@RESPATH@/components/gloda.manifest ; New message notification -@BINPATH@/components/newMailNotificationService.js +@RESPATH@/components/newMailNotificationService.js ; Address Sanitizer #ifdef MOZ_ASAN @@ -892,56 +873,56 @@ [chatzilla] #ifdef MOZ_OMNIJAR -@BINPATH@/distribution/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}.xpi +@RESPATH@/distribution/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}.xpi #else -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/chatzilla@JAREXT@ +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/chatzilla@JAREXT@ #ifdef MOZ_GTK2 -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/icons/default/chatzilla-window.xpm -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/icons/default/chatzilla-window16.xpm +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/icons/default/chatzilla-window.xpm +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/icons/default/chatzilla-window16.xpm #elifdef XP_WIN32 -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/icons/default/chatzilla-window.ico +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome/icons/default/chatzilla-window.ico #endif -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome.manifest -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/components/chatzilla-service.js -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/components/components.list -@BINPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/install.rdf +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/chrome.manifest +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/components/chatzilla-service.js +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/components/components.list +@RESPATH@/extensions/{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}/install.rdf #endif #ifdef LOCALE_BUILD #ifdef MOZ_OMNIJAR -@BINPATH@/distribution/extensions/langpack-@AB_CD@@chatzilla.mozilla.org.xpi +@RESPATH@/distribution/extensions/langpack-@AB_CD@@chatzilla.mozilla.org.xpi #else -@BINPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/chrome/chatzilla@JAREXT@ -@BINPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/chrome.manifest -@BINPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/install.js -@BINPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/install.rdf +@RESPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/chrome/chatzilla@JAREXT@ +@RESPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/chrome.manifest +@RESPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/install.js +@RESPATH@/extensions/langpack-@AB_CD@@chatzilla.mozilla.org/install.rdf #endif #endif [inspector] #ifdef MOZ_OMNIJAR -@BINPATH@/distribution/extensions/inspector@mozilla.org.xpi +@RESPATH@/distribution/extensions/inspector@mozilla.org.xpi #else -@BINPATH@/extensions/inspector@mozilla.org/install.rdf -@BINPATH@/extensions/inspector@mozilla.org/chrome.manifest -@BINPATH@/extensions/inspector@mozilla.org/chrome/inspector@JAREXT@ +@RESPATH@/extensions/inspector@mozilla.org/install.rdf +@RESPATH@/extensions/inspector@mozilla.org/chrome.manifest +@RESPATH@/extensions/inspector@mozilla.org/chrome/inspector@JAREXT@ #ifdef MOZ_GTK2 -@BINPATH@/extensions/inspector@mozilla.org/platform/Linux/chrome/icons/default/winInspectorMain16.xpm -@BINPATH@/extensions/inspector@mozilla.org/platform/Linux/chrome/icons/default/winInspectorMain.xpm +@RESPATH@/extensions/inspector@mozilla.org/platform/Linux/chrome/icons/default/winInspectorMain16.xpm +@RESPATH@/extensions/inspector@mozilla.org/platform/Linux/chrome/icons/default/winInspectorMain.xpm #elifdef XP_WIN32 -@BINPATH@/extensions/inspector@mozilla.org/platform/WINNT/chrome/icons/default/winInspectorMain.ico +@RESPATH@/extensions/inspector@mozilla.org/platform/WINNT/chrome/icons/default/winInspectorMain.ico #endif -@BINPATH@/extensions/inspector@mozilla.org/components/components.list -@BINPATH@/extensions/inspector@mozilla.org/components/inspector-cmdline.js -@BINPATH@/extensions/inspector@mozilla.org/defaults/preferences/inspector.js +@RESPATH@/extensions/inspector@mozilla.org/components/components.list +@RESPATH@/extensions/inspector@mozilla.org/components/inspector-cmdline.js +@RESPATH@/extensions/inspector@mozilla.org/defaults/preferences/inspector.js #endif [debugqa] #ifdef MOZ_PACKAGE_DEBUGQA #ifdef MOZ_OMNIJAR -@BINPATH@/distribution/extensions/debugQA@mozilla.org.xpi +@RESPATH@/distribution/extensions/debugQA@mozilla.org.xpi #else -@BINPATH@/extensions/debugQA@mozilla.org/install.rdf -@BINPATH@/extensions/debugQA@mozilla.org/chrome.manifest -@BINPATH@/extensions/debugQA@mozilla.org/chrome/debugqa@JAREXT@ +@RESPATH@/extensions/debugQA@mozilla.org/install.rdf +@RESPATH@/extensions/debugQA@mozilla.org/chrome.manifest +@RESPATH@/extensions/debugQA@mozilla.org/chrome/debugqa@JAREXT@ #endif #endif diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/common/dataman/dataman.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/common/dataman/dataman.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/common/dataman/dataman.properties 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/common/dataman/dataman.properties 2014-11-26 21:44:57.000000000 +0000 @@ -32,6 +32,7 @@ perm.stylesheet.label=Load Stylesheets perm.sts/use.label=Use Strict Transport Security perm.sts/subd.label=Apply Strict Transport Security to subdomains +perm.trackingprotection.label=Tracking Activity perm.type.default=Select a type diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/common/notification.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/common/notification.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/common/notification.properties 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/common/notification.properties 2014-11-26 21:44:58.000000000 +0000 @@ -16,14 +16,10 @@ carbonfailurepluginsMessage.button.accesskey=R missingpluginsMessage.title=Additional plugins are required to display all the media on this page. -missingpluginsMessage.button.label=Install Missing Plugins… -missingpluginsMessage.button.accesskey=I blockedpluginsMessage.title=Some plugins required by this page have been blocked for your protection. blockedpluginsMessage.infoButton.label=Details… blockedpluginsMessage.infoButton.accesskey=D -blockedpluginsMessage.searchButton.label=Update Plugins… -blockedpluginsMessage.searchButton.accesskey=U crashedpluginsMessage.title=The %S plugin has crashed. crashedpluginsMessage.reloadButton.label=Reload page @@ -184,8 +180,10 @@ SecurityTitle=Security Warning MixedContentMessage=You have requested an encrypted page that contains some unencrypted information. Information that you see or enter on this page could easily be read by a third party. MixedActiveContentMessage=You have requested an encrypted page that contains insecure information. Information that you see or enter on this page could easily be read by a third party. +TrackingContentMessage=Parts of this page may be tracking your online activity. MixedDisplayContentMessage=You have requested a page that is only partially encrypted and does not prevent eavesdropping. BlockedActiveContentMessage=Insecure information on this page was blocked. +BlockedTrackingContentMessage=Parts of the page that track your online activity were blocked. BlockedDisplayContentMessage=Unencrypted information on this page was blocked. EnterInsecureMessage=You have left an encrypted page. Information you send or receive from now on could easily be read by a third party. EnterSecureMessage=You have requested an encrypted page. The website has identified itself correctly, and information you see or enter on this page can't easily be read by a third party. diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/common/pref/pref-security.dtd thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/common/pref/pref-security.dtd --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/common/pref/pref-security.dtd 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/common/pref/pref-security.dtd 2014-11-26 21:44:58.000000000 +0000 @@ -12,6 +12,8 @@ + + diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/mailnews/charsetTitles.properties thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/mailnews/charsetTitles.properties --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/locales/en-US/chrome/mailnews/charsetTitles.properties 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/locales/en-US/chrome/mailnews/charsetTitles.properties 2014-11-26 21:44:58.000000000 +0000 @@ -35,21 +35,17 @@ euc-jp.title = Japanese (EUC-JP) big5.title = Chinese Traditional (Big5) big5-hkscs.title = Chinese Traditional (Big5-HKSCS) -x-euc-tw.title = Chinese Traditional (EUC-TW) gb2312.title = Chinese Simplified (GB2312) hz-gb-2312.title = Chinese Simplified (HZ) gbk.title = Chinese Simplified (GBK) -iso-2022-cn.title = Chinese Simplified (ISO-2022-CN) euc-kr.title = Korean (EUC-KR) x-johab.title = Korean (JOHAB) -iso-2022-kr.title = Korean (ISO-2022-KR) utf-7.title = Unicode (UTF-7) utf-8.title = Unicode (UTF-8) utf-16.title = Unicode (UTF-16) utf-16le.title = Unicode (UTF-16LE) utf-16be.title = Unicode (UTF-16BE) iso-8859-5.title = Cyrillic (ISO-8859-5) -iso-ir-111.title = Cyrillic (ISO-IR-111) windows-1251.title = Cyrillic (Windows-1251) x-mac-cyrillic.title = Cyrillic (MacCyrillic) x-mac-ukrainian.title = Cyrillic/Ukrainian (MacUkrainian) @@ -63,7 +59,6 @@ viscii.title = Vietnamese (VISCII) x-viet-vps.title = Vietnamese (VPS) windows-874.title = Thai (Windows-874) -ibm874.title = Thai (IBM-874) armscii-8.title = Armenian (ARMSCII-8) iso-8859-6.title = Arabic (ISO-8859-6) iso-8859-6-i.title = Arabic (ISO-8859-6-I) @@ -75,11 +70,6 @@ windows-1256.title = Arabic (Windows-1256) x-user-defined.title = User Defined ibm866.title = Cyrillic/Russian (CP-866) -ibm850.title = Western (IBM-850) -ibm852.title = Central European (IBM-852) -ibm855.title = Cyrillic (IBM-855) -ibm857.title = Turkish (IBM-857) -ibm862.title = Hebrew (IBM-862) gb18030.title = Chinese Simplified (GB18030) x-mac-arabic.title = Arabic (MacArabic) x-mac-farsi.title = Farsi (MacFarsi) @@ -88,7 +78,6 @@ x-mac-gujarati.title = Gujarati (MacGujarati) x-mac-gurmukhi.title = Gurmukhi (MacGurmukhi) - chardet.off.title = (Off) chardet.universal_charset_detector.title = Universal chardet.ja_parallel_state_machine.title = Japanese diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/mailnews/addrbook/abCommon.js thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/mailnews/addrbook/abCommon.js --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/mailnews/addrbook/abCommon.js 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/mailnews/addrbook/abCommon.js 2014-11-26 21:44:58.000000000 +0000 @@ -504,10 +504,19 @@ function goEditListDialog(abCard, listURI) { + var params = { + abCard: abCard, + listURI: listURI, + refresh: false, // This is an out param, true if OK in dialog is clicked. + }; + window.openDialog("chrome://messenger/content/addressbook/abEditListDialog.xul", "", "chrome,modal,resizable,centerscreen", - {abCard:abCard, listURI:listURI}); + params); + + if (params.refresh) + ChangeDirectoryByURI(listURI); // force refresh } function goNewCardDialog(selectedAB) diff -Nru thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/mailnews/addrbook/abListOverlay.xul thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/mailnews/addrbook/abListOverlay.xul --- thunderbird-trunk-36.0~a1~hg20141114r17084.215607/suite/mailnews/addrbook/abListOverlay.xul 2014-11-14 09:36:39.000000000 +0000 +++ thunderbird-trunk-36.0~a1~hg20141126r17147.217518/suite/mailnews/addrbook/abListOverlay.xul 2014-11-26 21:44:58.000000000 +0000 @@ -17,7 +17,6 @@