mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Merge last green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
d89ef2f8f8
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,7 +23,7 @@ ID
|
|||||||
security/manager/.nss.checkout
|
security/manager/.nss.checkout
|
||||||
|
|
||||||
# Build directories
|
# Build directories
|
||||||
obj/*
|
obj*/
|
||||||
|
|
||||||
# Build directories for js shell
|
# Build directories for js shell
|
||||||
*/_DBG.OBJ/
|
*/_DBG.OBJ/
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Hack to make xul:tabbrowser work
|
// Hacks to make xul:tabbrowser work
|
||||||
|
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const CC = Components.classes;
|
const CC = Components.classes;
|
||||||
@ -53,6 +53,8 @@
|
|||||||
|
|
||||||
var gFindBarInitialized = false;
|
var gFindBarInitialized = false;
|
||||||
|
|
||||||
|
function goSetCommandEnabled() {}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Tests
|
// Tests
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
*
|
*
|
||||||
@ -60,8 +62,8 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
|
|||||||
|
|
||||||
// In order to use http:// scheme instead of file:// scheme
|
// In order to use http:// scheme instead of file:// scheme
|
||||||
// (that is much more restricted) the following code kick-off
|
// (that is much more restricted) the following code kick-off
|
||||||
// a local http server listening on http://127.0.0.1:8888 and
|
// a local http server listening on http://127.0.0.1:7777 and
|
||||||
// http://localhost:8888.
|
// http://localhost:7777.
|
||||||
function startupHttpd(baseDir, port) {
|
function startupHttpd(baseDir, port) {
|
||||||
const httpdURL = 'chrome://browser/content/httpd.js';
|
const httpdURL = 'chrome://browser/content/httpd.js';
|
||||||
let httpd = {};
|
let httpd = {};
|
||||||
@ -91,6 +93,9 @@ function addPermissions(urls) {
|
|||||||
|
|
||||||
|
|
||||||
var shell = {
|
var shell = {
|
||||||
|
// FIXME/bug 678695: this should be a system setting
|
||||||
|
preferredScreenBrightness: 1.0,
|
||||||
|
|
||||||
get home() {
|
get home() {
|
||||||
delete this.home;
|
delete this.home;
|
||||||
return this.home = document.getElementById('homescreen');
|
return this.home = document.getElementById('homescreen');
|
||||||
@ -139,7 +144,7 @@ var shell = {
|
|||||||
baseDir.pop();
|
baseDir.pop();
|
||||||
baseDir = baseDir.join('/');
|
baseDir = baseDir.join('/');
|
||||||
|
|
||||||
const SERVER_PORT = 8888;
|
const SERVER_PORT = 6666;
|
||||||
startupHttpd(baseDir, SERVER_PORT);
|
startupHttpd(baseDir, SERVER_PORT);
|
||||||
|
|
||||||
let baseHost = 'http://localhost';
|
let baseHost = 'http://localhost';
|
||||||
@ -195,7 +200,7 @@ var shell = {
|
|||||||
this.sendEvent(this.home.contentWindow, 'home');
|
this.sendEvent(this.home.contentWindow, 'home');
|
||||||
break;
|
break;
|
||||||
case evt.DOM_VK_SLEEP:
|
case evt.DOM_VK_SLEEP:
|
||||||
screen.mozEnabled = !screen.mozEnabled;
|
this.toggleScreen();
|
||||||
break;
|
break;
|
||||||
case evt.DOM_VK_ESCAPE:
|
case evt.DOM_VK_ESCAPE:
|
||||||
if (evt.defaultPrevented)
|
if (evt.defaultPrevented)
|
||||||
@ -206,6 +211,7 @@ var shell = {
|
|||||||
break;
|
break;
|
||||||
case 'load':
|
case 'load':
|
||||||
this.home.removeEventListener('load', this, true);
|
this.home.removeEventListener('load', this, true);
|
||||||
|
this.turnScreenOn();
|
||||||
this.sendEvent(window, 'ContentStart');
|
this.sendEvent(window, 'ContentStart');
|
||||||
break;
|
break;
|
||||||
case 'MozApplicationManifest':
|
case 'MozApplicationManifest':
|
||||||
@ -248,7 +254,21 @@ var shell = {
|
|||||||
let event = content.document.createEvent('CustomEvent');
|
let event = content.document.createEvent('CustomEvent');
|
||||||
event.initCustomEvent(type, true, true, details ? details : {});
|
event.initCustomEvent(type, true, true, details ? details : {});
|
||||||
content.dispatchEvent(event);
|
content.dispatchEvent(event);
|
||||||
}
|
},
|
||||||
|
toggleScreen: function shell_toggleScreen() {
|
||||||
|
if (screen.mozEnabled)
|
||||||
|
this.turnScreenOff();
|
||||||
|
else
|
||||||
|
this.turnScreenOn();
|
||||||
|
},
|
||||||
|
turnScreenOff: function shell_turnScreenOff() {
|
||||||
|
screen.mozEnabled = false;
|
||||||
|
screen.mozBrightness = 0.0;
|
||||||
|
},
|
||||||
|
turnScreenOn: function shell_turnScreenOn() {
|
||||||
|
screen.mozEnabled = true;
|
||||||
|
screen.mozBrightness = this.preferredScreenBrightness;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
(function VirtualKeyboardManager() {
|
(function VirtualKeyboardManager() {
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
id="shell"
|
id="shell"
|
||||||
width="480" height="800"
|
width="480" height="800"
|
||||||
|
windowtype="navigator:browser"
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
sizemode="fullscreen"
|
sizemode="fullscreen"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
|
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
|
||||||
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
|
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
|
||||||
// The time interval between checks for a new version (in seconds)
|
// The time interval between checks for a new version (in seconds)
|
||||||
pref("app.update.interval", 7200); // 2 hours
|
pref("app.update.interval", 3600); // 1 hour
|
||||||
// The time interval between the downloading of mar file chunks in the
|
// The time interval between the downloading of mar file chunks in the
|
||||||
// background (in seconds)
|
// background (in seconds)
|
||||||
pref("app.update.download.backgroundInterval", 60);
|
pref("app.update.download.backgroundInterval", 60);
|
||||||
// Give the user x seconds to react before showing the big UI. default=12 hours
|
// Give the user x seconds to react before showing the big UI. default=1 hour
|
||||||
pref("app.update.promptWaitTime", 43200);
|
pref("app.update.promptWaitTime", 3600);
|
||||||
// URL user can browse to manually if for some reason all update installation
|
// URL user can browse to manually if for some reason all update installation
|
||||||
// attempts fail.
|
// attempts fail.
|
||||||
pref("app.update.url.manual", "http://nightly.mozilla.org/");
|
pref("app.update.url.manual", "http://nightly.mozilla.org/");
|
||||||
|
@ -42,8 +42,13 @@
|
|||||||
* to remove all traces of visiting a site.
|
* to remove all traces of visiting a site.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing-wrapper;1";
|
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing-wrapper;1";
|
||||||
load("do_test_removeDataFromDomain.js");
|
load("do_test_removeDataFromDomain.js");
|
||||||
do_test();
|
do_test();
|
||||||
|
|
||||||
|
// Shutdown the download manager.
|
||||||
|
Services.obs.notifyObservers(null, "quit-application", null);
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,13 @@
|
|||||||
* to remove all traces of visiting a site.
|
* to remove all traces of visiting a site.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
||||||
load("do_test_removeDataFromDomain_activeDownloads.js");
|
load("do_test_removeDataFromDomain_activeDownloads.js");
|
||||||
do_test();
|
do_test();
|
||||||
|
|
||||||
|
// Shutdown the download manager.
|
||||||
|
Services.obs.notifyObservers(null, "quit-application", null);
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,13 @@
|
|||||||
* to remove all traces of visiting a site.
|
* to remove all traces of visiting a site.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
||||||
load("do_test_removeDataFromDomain.js");
|
load("do_test_removeDataFromDomain.js");
|
||||||
do_test();
|
do_test();
|
||||||
|
|
||||||
|
// Shutdown the download manager.
|
||||||
|
Services.obs.notifyObservers(null, "quit-application", null);
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,13 @@
|
|||||||
* to remove all traces of visiting a site.
|
* to remove all traces of visiting a site.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
||||||
load("do_test_removeDataFromDomain_activeDownloads.js");
|
load("do_test_removeDataFromDomain_activeDownloads.js");
|
||||||
do_test();
|
do_test();
|
||||||
|
|
||||||
|
// Shutdown the download manager.
|
||||||
|
Services.obs.notifyObservers(null, "quit-application", null);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#navigator-toolbox > toolbar:not(:-moz-lwtheme),
|
#navigator-toolbox > toolbar:not(:-moz-lwtheme),
|
||||||
#browser-bottombox:not(:-moz-lwtheme) {
|
#browser-bottombox:not(:-moz-lwtheme) {
|
||||||
background-color: @customToolbarColor@;
|
background-color: @customToolbarColor@;
|
||||||
@ -82,7 +82,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-compositor) {
|
@media (-moz-windows-compositor) {
|
||||||
/* These should be hidden w/ glass enabled. Windows draws its own buttons. */
|
/* These should be hidden w/ glass enabled. Windows draws its own buttons. */
|
||||||
.titlebar-button {
|
.titlebar-button {
|
||||||
display: none;
|
display: none;
|
||||||
@ -348,7 +348,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ::::: splitmenu highlight style that imitates Windows 7 start menu ::::: */
|
/* ::::: splitmenu highlight style that imitates Windows 7 start menu ::::: */
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
.splitmenu-menuitem,
|
.splitmenu-menuitem,
|
||||||
.splitmenu-menu {
|
.splitmenu-menu {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
@ -165,14 +165,14 @@
|
|||||||
margin: 0 0 2px;
|
margin: 0 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-classic) {
|
@media (-moz-windows-classic) {
|
||||||
#appmenu-button {
|
#appmenu-button {
|
||||||
margin-bottom: 1px;
|
margin-bottom: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%ifndef WINSTRIPE_AERO
|
%ifndef WINSTRIPE_AERO
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#main-window[sizemode="normal"] #appmenu-button {
|
#main-window[sizemode="normal"] #appmenu-button {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@
|
|||||||
-moz-border-end: 1px solid ThreeDShadow;
|
-moz-border-end: 1px solid ThreeDShadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#appmenu-popup {
|
#appmenu-popup {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
background: white;
|
background: white;
|
||||||
@ -483,7 +483,7 @@
|
|||||||
-moz-appearance: -moz-window-titlebar-maximized;
|
-moz-appearance: -moz-window-titlebar-maximized;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-classic) {
|
@media (-moz-windows-classic) {
|
||||||
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container {
|
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
@ -1214,7 +1214,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
|||||||
-moz-padding-end: 2px;
|
-moz-padding-end: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#urlbar,
|
#urlbar,
|
||||||
.searchbar-textbox {
|
.searchbar-textbox {
|
||||||
@navbarTextboxCustomBorder@
|
@navbarTextboxCustomBorder@
|
||||||
@ -1712,7 +1712,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||||||
margin: 16px 0 -2px;
|
margin: 16px 0 -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
.panel-promo-box {
|
.panel-promo-box {
|
||||||
margin: 8px -16px -16px;
|
margin: 8px -16px -16px;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
@ -1795,7 +1795,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||||||
}
|
}
|
||||||
|
|
||||||
%ifndef WINSTRIPE_AERO
|
%ifndef WINSTRIPE_AERO
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#main-window[sizemode=normal] #TabsToolbar {
|
#main-window[sizemode=normal] #TabsToolbar {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
@ -1827,7 +1827,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||||||
}
|
}
|
||||||
|
|
||||||
%ifndef WINSTRIPE_AERO
|
%ifndef WINSTRIPE_AERO
|
||||||
@media all and (-moz-windows-theme: luna-blue) {
|
@media (-moz-windows-theme: luna-blue) {
|
||||||
.tabbrowser-tab,
|
.tabbrowser-tab,
|
||||||
.tabs-newtab-button {
|
.tabs-newtab-button {
|
||||||
background-image: @toolbarShadowOnTab@,
|
background-image: @toolbarShadowOnTab@,
|
||||||
@ -1956,7 +1956,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||||||
|
|
||||||
/* Tab scrollbox arrow, tabstrip new tab and all-tabs buttons */
|
/* Tab scrollbox arrow, tabstrip new tab and all-tabs buttons */
|
||||||
|
|
||||||
@media all and (-moz-touch-enabled) {
|
@media (-moz-touch-enabled) {
|
||||||
.tabbrowser-arrowscrollbox > .scrollbutton-up,
|
.tabbrowser-arrowscrollbox > .scrollbutton-up,
|
||||||
.tabbrowser-arrowscrollbox > .scrollbutton-down,
|
.tabbrowser-arrowscrollbox > .scrollbutton-down,
|
||||||
#TabsToolbar .toolbarbutton-1 {
|
#TabsToolbar .toolbarbutton-1 {
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-compositor) {
|
@media (-moz-windows-compositor) {
|
||||||
#placesToolbox {
|
#placesToolbox {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
@ -31,7 +31,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#placesView,
|
#placesView,
|
||||||
#searchModifiers,
|
#searchModifiers,
|
||||||
#infoPane,
|
#infoPane,
|
||||||
|
@ -44,13 +44,22 @@ public interface Actions {
|
|||||||
public enum SpecialKey {
|
public enum SpecialKey {
|
||||||
DOWN, UP, LEFT, RIGHT, ENTER
|
DOWN, UP, LEFT, RIGHT, ENTER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface EventExpecter {
|
||||||
|
/** Blocks until the event has been received. Subsequent calls will return immediately. */
|
||||||
|
public void blockForEvent();
|
||||||
|
/** Polls to see if the event has been received. Once this returns true, subsequent calls will also return true. */
|
||||||
|
public boolean eventReceived();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for a gecko event to be sent from the Gecko instance.
|
* Listens for a gecko event to be sent from the Gecko instance.
|
||||||
|
* The returned object can be used to test if the event has been
|
||||||
|
* received. Note that only one event is listened for.
|
||||||
*
|
*
|
||||||
* @param geckoEvent The geckoEvent JSONObject's type
|
* @param geckoEvent The geckoEvent JSONObject's type
|
||||||
*/
|
*/
|
||||||
|
EventExpecter expectGeckoEvent(String geckoEvent);
|
||||||
void waitForGeckoEvent(String geckoEvent);
|
|
||||||
// Send the string kewsToSend to the application
|
// Send the string kewsToSend to the application
|
||||||
void sendKeys(String keysToSend);
|
void sendKeys(String keysToSend);
|
||||||
//Send any of the above keys to the element
|
//Send any of the above keys to the element
|
||||||
|
@ -38,17 +38,20 @@
|
|||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
package @ANDROID_PACKAGE_NAME@;
|
package @ANDROID_PACKAGE_NAME@;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
public interface Driver {
|
public interface Driver {
|
||||||
/**
|
/**
|
||||||
* Find the first Element using the given method.
|
* Find the first Element using the given method.
|
||||||
*
|
*
|
||||||
|
* @param activity The activity the element belongs to
|
||||||
* @param name The name of the element
|
* @param name The name of the element
|
||||||
* @return The first matching element on the current context
|
* @return The first matching element on the current context
|
||||||
* @throws RoboCopException If no matching elements are found
|
* @throws RoboCopException If no matching elements are found
|
||||||
*/
|
*/
|
||||||
Element findElement(String name);
|
Element findElement(Activity activity, String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up scroll handling so that data is received from the extension.
|
* Sets up scroll handling so that data is received from the extension.
|
||||||
|
@ -84,9 +84,6 @@ public class FennecNativeActions implements Actions {
|
|||||||
private Method sendGE;
|
private Method sendGE;
|
||||||
|
|
||||||
|
|
||||||
// If waiting for an event.
|
|
||||||
private SynchronousQueue waitqueue = new SynchronousQueue<Boolean>();
|
|
||||||
|
|
||||||
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation){
|
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation){
|
||||||
this.solo = robocop;
|
this.solo = robocop;
|
||||||
this.instr = instrumentation;
|
this.instr = instrumentation;
|
||||||
@ -116,7 +113,12 @@ public class FennecNativeActions implements Actions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class wakeInvocationHandler implements InvocationHandler {
|
class wakeInvocationHandler implements InvocationHandler {
|
||||||
public wakeInvocationHandler(){};
|
private final GeckoEventExpecter mEventExpecter;
|
||||||
|
|
||||||
|
public wakeInvocationHandler(GeckoEventExpecter expecter) {
|
||||||
|
mEventExpecter = expecter;
|
||||||
|
}
|
||||||
|
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||||
String methodName = method.getName();
|
String methodName = method.getName();
|
||||||
//Depending on the method, return a completely different type.
|
//Depending on the method, return a completely different type.
|
||||||
@ -133,12 +135,54 @@ public class FennecNativeActions implements Actions {
|
|||||||
return 314;
|
return 314;
|
||||||
}
|
}
|
||||||
Log.i("Robocop", "Waking up on "+methodName);
|
Log.i("Robocop", "Waking up on "+methodName);
|
||||||
waitqueue.offer(new Boolean(true));
|
mEventExpecter.notifyOfEvent();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GeckoEventExpecter implements EventExpecter {
|
||||||
|
private final String mGeckoEvent;
|
||||||
|
private final Object[] mRegistrationParams;
|
||||||
|
private boolean mEventReceived;
|
||||||
|
|
||||||
|
GeckoEventExpecter(String geckoEvent, Object[] registrationParams) {
|
||||||
|
mGeckoEvent = geckoEvent;
|
||||||
|
mRegistrationParams = registrationParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void blockForEvent() {
|
||||||
|
while (! mEventReceived) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.i("Robocop", "unblocked on expecter for " + mGeckoEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean eventReceived() {
|
||||||
|
return mEventReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyOfEvent() {
|
||||||
|
try {
|
||||||
|
unregisterGEL.invoke(null, mRegistrationParams);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Log.i("Robocop", "received event " + mGeckoEvent);
|
||||||
|
synchronized (this) {
|
||||||
|
mEventReceived = true;
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void waitForGeckoEvent(String geckoEvent) {
|
public EventExpecter expectGeckoEvent(String geckoEvent) {
|
||||||
Log.i("Robocop", "waiting for "+geckoEvent);
|
Log.i("Robocop", "waiting for "+geckoEvent);
|
||||||
try {
|
try {
|
||||||
Class [] interfaces = new Class[1];
|
Class [] interfaces = new Class[1];
|
||||||
@ -146,21 +190,19 @@ public class FennecNativeActions implements Actions {
|
|||||||
Object[] finalParams = new Object[2];
|
Object[] finalParams = new Object[2];
|
||||||
finalParams[0] = geckoEvent;
|
finalParams[0] = geckoEvent;
|
||||||
|
|
||||||
wakeInvocationHandler wIH = new wakeInvocationHandler();
|
GeckoEventExpecter expecter = new GeckoEventExpecter(geckoEvent, finalParams);
|
||||||
|
wakeInvocationHandler wIH = new wakeInvocationHandler(expecter);
|
||||||
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, wIH);
|
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, wIH);
|
||||||
finalParams[1] = proxy;
|
finalParams[1] = proxy;
|
||||||
registerGEL.invoke(null, finalParams);
|
registerGEL.invoke(null, finalParams);
|
||||||
|
|
||||||
waitqueue.take();
|
return expecter;
|
||||||
unregisterGEL.invoke(null, finalParams);
|
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
Log.i("Robocop", "wait ends for: "+geckoEvent);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendSpecialKey(SpecialKey button) {
|
public void sendSpecialKey(SpecialKey button) {
|
||||||
|
@ -167,8 +167,7 @@ public class FennecNativeDriver implements Driver {
|
|||||||
return geckoWidth;
|
return geckoWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Element findElement(Activity activity, String name) {
|
||||||
public Element findElement(String name) {
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throw new IllegalArgumentException("Can not findElements when passed a null");
|
throw new IllegalArgumentException("Can not findElements when passed a null");
|
||||||
if (locators.containsKey(name)){
|
if (locators.containsKey(name)){
|
||||||
|
@ -56,28 +56,26 @@ import com.jayway.android.robotium.solo.Solo;
|
|||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
|
|
||||||
public class FennecNativeElement implements Element {
|
public class FennecNativeElement implements Element {
|
||||||
|
private final Activity mActivity;
|
||||||
private Integer id;
|
private Integer id;
|
||||||
private Activity currentActivity;
|
|
||||||
private Solo robocop;
|
private Solo robocop;
|
||||||
|
|
||||||
public FennecNativeElement(Integer id, Activity activity, Solo solo){
|
public FennecNativeElement(Integer id, Activity activity, Solo solo){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
mActivity = activity;
|
||||||
robocop = solo;
|
robocop = solo;
|
||||||
currentActivity = activity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void click() {
|
public void click() {
|
||||||
final SynchronousQueue syncQueue = new SynchronousQueue();
|
final SynchronousQueue syncQueue = new SynchronousQueue();
|
||||||
currentActivity = robocop.getCurrentActivity();
|
mActivity.runOnUiThread(
|
||||||
currentActivity.runOnUiThread(
|
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
View view = (View)currentActivity.findViewById(id);
|
View view = (View)mActivity.findViewById(id);
|
||||||
if(view != null) {
|
if(view != null) {
|
||||||
view.performClick();
|
view.performClick();
|
||||||
} else {
|
} else {
|
||||||
@ -94,16 +92,13 @@ public class FennecNativeElement implements Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object text;
|
private Object text;
|
||||||
private Activity elementActivity;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
elementActivity = robocop.getCurrentActivity();
|
|
||||||
final SynchronousQueue syncQueue = new SynchronousQueue();
|
final SynchronousQueue syncQueue = new SynchronousQueue();
|
||||||
elementActivity.runOnUiThread(
|
mActivity.runOnUiThread(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
View v = elementActivity.findViewById(id);
|
View v = mActivity.findViewById(id);
|
||||||
if(v instanceof EditText) {
|
if(v instanceof EditText) {
|
||||||
EditText et = (EditText)v;
|
EditText et = (EditText)v;
|
||||||
text = et.getEditableText();
|
text = et.getEditableText();
|
||||||
@ -143,15 +138,13 @@ public class FennecNativeElement implements Element {
|
|||||||
|
|
||||||
private boolean displayed;
|
private boolean displayed;
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDisplayed() {
|
public boolean isDisplayed() {
|
||||||
final SynchronousQueue syncQueue = new SynchronousQueue();
|
final SynchronousQueue syncQueue = new SynchronousQueue();
|
||||||
currentActivity = robocop.getCurrentActivity();
|
|
||||||
displayed = false;
|
displayed = false;
|
||||||
currentActivity.runOnUiThread(
|
mActivity.runOnUiThread(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
View view = (View)currentActivity.findViewById(id);
|
View view = (View)mActivity.findViewById(id);
|
||||||
if(view != null) {
|
if(view != null) {
|
||||||
displayed = true;
|
displayed = true;
|
||||||
}
|
}
|
||||||
|
@ -8907,16 +8907,9 @@ nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
|
|||||||
// Remember this is the requesting full-screen document.
|
// Remember this is the requesting full-screen document.
|
||||||
sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
|
sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
|
||||||
|
|
||||||
// Make the window full-screen. Note we must make the state changes above
|
|
||||||
// before making the window full-screen, as then the document reports as
|
|
||||||
// being in full-screen mode when the chrome "fullscreen" event fires,
|
|
||||||
// enabling chrome to distinguish between browser and dom full-screen
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
// Note assertions must run before SetWindowFullScreen() as that does
|
||||||
|
// synchronous event dispatch which can run script which exits full-screen!
|
||||||
NS_ASSERTION(GetFullScreenElement() == aElement,
|
NS_ASSERTION(GetFullScreenElement() == aElement,
|
||||||
"Full-screen element should be the requested element!");
|
"Full-screen element should be the requested element!");
|
||||||
NS_ASSERTION(IsFullScreenDoc(), "Should be full-screen doc");
|
NS_ASSERTION(IsFullScreenDoc(), "Should be full-screen doc");
|
||||||
@ -8926,6 +8919,15 @@ nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
|
|||||||
NS_ASSERTION(c->AsElement() == aElement,
|
NS_ASSERTION(c->AsElement() == aElement,
|
||||||
"GetMozFullScreenElement should match GetFullScreenElement()");
|
"GetMozFullScreenElement should match GetFullScreenElement()");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Make the window full-screen. Note we must make the state changes above
|
||||||
|
// before making the window full-screen, as then the document reports as
|
||||||
|
// being in full-screen mode when the chrome "fullscreen" event fires,
|
||||||
|
// enabling chrome to distinguish between browser and dom full-screen
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -1568,6 +1568,7 @@ nsWebSocket::Cancel(nsresult aStatus)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
ConsoleError();
|
ConsoleError();
|
||||||
|
mClientReasonCode = nsIWebSocketChannel::CLOSE_GOING_AWAY;
|
||||||
return CloseConnection();
|
return CloseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,6 +302,11 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest*
|
|||||||
{
|
{
|
||||||
nsContentUtils::UnregisterShutdownObserver(this);
|
nsContentUtils::UnregisterShutdownObserver(this);
|
||||||
|
|
||||||
|
if (!mElement) {
|
||||||
|
// We've been notified by the shutdown observer, and are shutting down.
|
||||||
|
return NS_BINDING_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// The element is only needed until we've had a chance to call
|
// The element is only needed until we've had a chance to call
|
||||||
// InitializeDecoderForChannel. So make sure mElement is cleared here.
|
// InitializeDecoderForChannel. So make sure mElement is cleared here.
|
||||||
nsRefPtr<nsHTMLMediaElement> element;
|
nsRefPtr<nsHTMLMediaElement> element;
|
||||||
|
@ -273,7 +273,7 @@ nsresult nsBuiltinDecoder::Play()
|
|||||||
* Returns true if aValue is inside a range of aRanges, and put the range
|
* Returns true if aValue is inside a range of aRanges, and put the range
|
||||||
* index in aIntervalIndex if it is not null.
|
* index in aIntervalIndex if it is not null.
|
||||||
* If aValue is not inside a range, false is returned, and aIntervalIndex, if
|
* If aValue is not inside a range, false is returned, and aIntervalIndex, if
|
||||||
* not null, is set to the index of the range which ends immediatly before aValue
|
* not null, is set to the index of the range which ends immediately before aValue
|
||||||
* (and can be -1 if aValue is before aRanges.Start(0)).
|
* (and can be -1 if aValue is before aRanges.Start(0)).
|
||||||
*/
|
*/
|
||||||
static bool IsInRanges(nsTimeRanges& aRanges, double aValue, PRInt32& aIntervalIndex) {
|
static bool IsInRanges(nsTimeRanges& aRanges, double aValue, PRInt32& aIntervalIndex) {
|
||||||
@ -315,30 +315,32 @@ nsresult nsBuiltinDecoder::Seek(double aTime)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the position we want to seek to is not in a seekable range, we seek
|
// If the position we want to seek to is not in a seekable range, we seek
|
||||||
// to the closest position in the seekable ranges instead . If two positions
|
// to the closest position in the seekable ranges instead. If two positions
|
||||||
// are equaly close, we seek to the closest position from the currentTime.
|
// are equally close, we seek to the closest position from the currentTime.
|
||||||
// See seeking spec, point 7 :
|
// See seeking spec, point 7 :
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#seeking
|
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#seeking
|
||||||
PRInt32 range = 0;
|
PRInt32 range = 0;
|
||||||
if (!IsInRanges(seekable, aTime, range)) {
|
if (!IsInRanges(seekable, aTime, range)) {
|
||||||
if (range != -1) {
|
if (range != -1) {
|
||||||
double leftBound, rightBound;
|
|
||||||
res = seekable.End(range, &leftBound);
|
|
||||||
NS_ENSURE_SUCCESS(res, NS_OK);
|
|
||||||
double distanceLeft = NS_ABS(leftBound - aTime);
|
|
||||||
|
|
||||||
double distanceRight = -1;
|
|
||||||
if (range + 1 < length) {
|
if (range + 1 < length) {
|
||||||
res = seekable.Start(range+1, &rightBound);
|
double leftBound, rightBound;
|
||||||
|
res = seekable.End(range, &leftBound);
|
||||||
|
NS_ENSURE_SUCCESS(res, NS_OK);
|
||||||
|
res = seekable.Start(range + 1, &rightBound);
|
||||||
|
NS_ENSURE_SUCCESS(res, NS_OK);
|
||||||
|
double distanceLeft = NS_ABS(leftBound - aTime);
|
||||||
|
double distanceRight = NS_ABS(rightBound - aTime);
|
||||||
|
if (distanceLeft == distanceRight) {
|
||||||
|
distanceLeft = NS_ABS(leftBound - mCurrentTime);
|
||||||
|
distanceRight = NS_ABS(rightBound - mCurrentTime);
|
||||||
|
}
|
||||||
|
aTime = (distanceLeft < distanceRight) ? leftBound : rightBound;
|
||||||
|
} else {
|
||||||
|
// Seek target is after the end last range in seekable data.
|
||||||
|
// Clamp the seek target to the end of the last seekable range.
|
||||||
|
res = seekable.End(length - 1, &aTime);
|
||||||
NS_ENSURE_SUCCESS(res, NS_OK);
|
NS_ENSURE_SUCCESS(res, NS_OK);
|
||||||
distanceRight = NS_ABS(rightBound - aTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (distanceLeft == distanceRight) {
|
|
||||||
distanceLeft = NS_ABS(leftBound - mCurrentTime);
|
|
||||||
distanceRight = NS_ABS(rightBound - mCurrentTime);
|
|
||||||
}
|
|
||||||
aTime = (distanceLeft < distanceRight) ? leftBound : rightBound;
|
|
||||||
} else {
|
} else {
|
||||||
// aTime is before the first range in |seekable|, the closest point we can
|
// aTime is before the first range in |seekable|, the closest point we can
|
||||||
// seek to is the start of the first range.
|
// seek to is the start of the first range.
|
||||||
|
@ -1124,6 +1124,33 @@ void nsBuiltinDecoderStateMachine::ResetPlayback()
|
|||||||
mAudioCompleted = false;
|
mAudioCompleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsBuiltinDecoderStateMachine::NotifyDataArrived(const char* aBuffer,
|
||||||
|
PRUint32 aLength,
|
||||||
|
PRUint32 aOffset)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||||
|
mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
|
||||||
|
|
||||||
|
// While playing an unseekable stream of unknown duration, mEndTime is
|
||||||
|
// updated (in AdvanceFrame()) as we play. But if data is being downloaded
|
||||||
|
// faster than played, mEndTime won't reflect the end of playable data
|
||||||
|
// since we haven't played the frame at the end of buffered data. So update
|
||||||
|
// mEndTime here as new data is downloaded to prevent such a lag.
|
||||||
|
nsTimeRanges buffered;
|
||||||
|
if (mDecoder->IsInfinite() &&
|
||||||
|
NS_SUCCEEDED(mDecoder->GetBuffered(&buffered)))
|
||||||
|
{
|
||||||
|
PRUint32 length = 0;
|
||||||
|
buffered.GetLength(&length);
|
||||||
|
if (length) {
|
||||||
|
double end = 0;
|
||||||
|
buffered.End(length - 1, &end);
|
||||||
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
|
mEndTime = NS_MAX<PRInt64>(mEndTime, end * USECS_PER_S);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoderStateMachine::Seek(double aTime)
|
void nsBuiltinDecoderStateMachine::Seek(double aTime)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||||
@ -1505,7 +1532,11 @@ void nsBuiltinDecoderStateMachine::DecodeSeek()
|
|||||||
// if we need to seek again.
|
// if we need to seek again.
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> stopEvent;
|
nsCOMPtr<nsIRunnable> stopEvent;
|
||||||
if (GetMediaTime() == mEndTime) {
|
bool isLiveStream = mDecoder->GetStream()->GetLength() == -1;
|
||||||
|
if (GetMediaTime() == mEndTime && !isLiveStream) {
|
||||||
|
// Seeked to end of media, move to COMPLETED state. Note we don't do
|
||||||
|
// this if we're playing a live stream, since the end of media will advance
|
||||||
|
// once we download more data!
|
||||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to COMPLETED",
|
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to COMPLETED",
|
||||||
mDecoder.get(), seekTime));
|
mDecoder.get(), seekTime));
|
||||||
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStoppedAtEnd);
|
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStoppedAtEnd);
|
||||||
|
@ -223,10 +223,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset) {
|
void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset);
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
|
||||||
mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRInt64 GetEndMediaTime() const {
|
PRInt64 GetEndMediaTime() const {
|
||||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||||
|
@ -1619,6 +1619,55 @@ nsDOMWindowUtils::GetLayerManagerType(nsAString& aType)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMWindowUtils::StartFrameTimeRecording()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||||
|
if (!widget)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
LayerManager *mgr = widget->GetLayerManager();
|
||||||
|
if (!mgr)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
mgr->StartFrameTimeRecording();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMWindowUtils::StopFrameTimeRecording(PRUint32 *frameCount NS_OUTPARAM, float **frames NS_OUTPARAM)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(frameCount);
|
||||||
|
NS_ENSURE_ARG_POINTER(frames);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||||
|
if (!widget)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
LayerManager *mgr = widget->GetLayerManager();
|
||||||
|
if (!mgr)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
nsTArray<float> frameTimes = mgr->StopFrameTimeRecording();
|
||||||
|
|
||||||
|
*frames = nsnull;
|
||||||
|
*frameCount = frameTimes.Length();
|
||||||
|
|
||||||
|
if (*frameCount != 0) {
|
||||||
|
*frames = (float*)nsMemory::Alloc(*frameCount * sizeof(float*));
|
||||||
|
if (!*frames)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* copy over the frame times into the array we just allocated */
|
||||||
|
for (PRUint32 i = 0; i < *frameCount; i++) {
|
||||||
|
(*frames)[i] = frameTimes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ComputeAnimationValue(nsCSSProperty aProperty,
|
ComputeAnimationValue(nsCSSProperty aProperty,
|
||||||
Element* aElement,
|
Element* aElement,
|
||||||
|
@ -252,13 +252,6 @@ IndexedDatabaseManager::GetOrCreate()
|
|||||||
false);
|
false);
|
||||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||||
|
|
||||||
// We don't really need this callback but we want the observer service to
|
|
||||||
// hold us alive until XPCOM shutdown. That way other consumers can continue
|
|
||||||
// to use this service until shutdown.
|
|
||||||
rv = obs->AddObserver(instance, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
|
|
||||||
false);
|
|
||||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
||||||
|
|
||||||
// Make a lazy thread for any IO we need (like clearing or enumerating the
|
// Make a lazy thread for any IO we need (like clearing or enumerating the
|
||||||
// contents of indexedDB database directories).
|
// contents of indexedDB database directories).
|
||||||
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
|
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
|
||||||
@ -1224,7 +1217,7 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID)) {
|
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||||
// Setting this flag prevents the service from being recreated and prevents
|
// Setting this flag prevents the service from being recreated and prevents
|
||||||
// further databases from being created.
|
// further databases from being created.
|
||||||
if (PR_ATOMIC_SET(&gShutdown, 1)) {
|
if (PR_ATOMIC_SET(&gShutdown, 1)) {
|
||||||
@ -1279,11 +1272,6 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
|
||||||
// We're dying now.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_NOTREACHED("Unknown topic!");
|
NS_NOTREACHED("Unknown topic!");
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ interface nsIDOMBlob;
|
|||||||
interface nsIDOMFile;
|
interface nsIDOMFile;
|
||||||
interface nsIFile;
|
interface nsIFile;
|
||||||
|
|
||||||
[scriptable, uuid(c1fa9c82-acf2-4b27-8ca7-7d1864e606af)]
|
[scriptable, uuid(15fcceb0-37ea-11e1-b86c-0800200c9a66)]
|
||||||
interface nsIDOMWindowUtils : nsISupports {
|
interface nsIDOMWindowUtils : nsISupports {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -838,6 +838,9 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||||||
*/
|
*/
|
||||||
readonly attribute AString layerManagerType;
|
readonly attribute AString layerManagerType;
|
||||||
|
|
||||||
|
void startFrameTimeRecording();
|
||||||
|
void stopFrameTimeRecording([optional] out unsigned long frameCount,
|
||||||
|
[retval, array, size_is(frameCount)] out float frameTime);
|
||||||
/**
|
/**
|
||||||
* The DPI of the display
|
* The DPI of the display
|
||||||
*/
|
*/
|
||||||
|
@ -208,7 +208,7 @@ nsDOMStoragePersistentDB::Init(const nsString& aDatabaseName)
|
|||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA temp_store = MEMORY"));
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA temp_store = MEMORY"));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
mozStorageTransaction transaction(mConnection, false);
|
mozStorageTransaction transaction(mConnection, false);
|
||||||
|
@ -561,6 +561,31 @@ PlanarYCbCrImage::CopyData(Data& aDest, gfxIntSize& aDestSize,
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LayerManager::StartFrameTimeRecording()
|
||||||
|
{
|
||||||
|
mLastFrameTime = TimeStamp::Now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LayerManager::PostPresent()
|
||||||
|
{
|
||||||
|
if (!mLastFrameTime.IsNull()) {
|
||||||
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
mFrameTimes.AppendElement((now - mLastFrameTime).ToMilliseconds());
|
||||||
|
mLastFrameTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<float>
|
||||||
|
LayerManager::StopFrameTimeRecording()
|
||||||
|
{
|
||||||
|
mLastFrameTime = TimeStamp();
|
||||||
|
nsTArray<float> result = mFrameTimes;
|
||||||
|
mFrameTimes.Clear();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(PR_LOGGING)
|
#if defined(DEBUG) || defined(PR_LOGGING)
|
||||||
# include <stdio.h> // FILE
|
# include <stdio.h> // FILE
|
||||||
@ -512,6 +513,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void LogSelf(const char* aPrefix="");
|
void LogSelf(const char* aPrefix="");
|
||||||
|
|
||||||
|
void StartFrameTimeRecording();
|
||||||
|
nsTArray<float> StopFrameTimeRecording();
|
||||||
|
|
||||||
|
void PostPresent();
|
||||||
|
|
||||||
static bool IsLogEnabled();
|
static bool IsLogEnabled();
|
||||||
static PRLogModuleInfo* GetLog() { return sLog; }
|
static PRLogModuleInfo* GetLog() { return sLog; }
|
||||||
|
|
||||||
@ -532,6 +538,9 @@ protected:
|
|||||||
|
|
||||||
static void InitLog();
|
static void InitLog();
|
||||||
static PRLogModuleInfo* sLog;
|
static PRLogModuleInfo* sLog;
|
||||||
|
private:
|
||||||
|
TimeStamp mLastFrameTime;
|
||||||
|
nsTArray<float> mFrameTimes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThebesLayer;
|
class ThebesLayer;
|
||||||
|
@ -778,6 +778,7 @@ LayerManagerD3D10::Render()
|
|||||||
} else {
|
} else {
|
||||||
mSwapChain->Present(0, 0);
|
mSwapChain->Present(0, 0);
|
||||||
}
|
}
|
||||||
|
LayerManager::PostPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -354,6 +354,7 @@ LayerManagerD3D9::Render()
|
|||||||
(r = iter.Next()) != nsnull;) {
|
(r = iter.Next()) != nsnull;) {
|
||||||
mSwapChain->Present(*r);
|
mSwapChain->Present(*r);
|
||||||
}
|
}
|
||||||
|
LayerManager::PostPresent();
|
||||||
} else {
|
} else {
|
||||||
PaintToTarget();
|
PaintToTarget();
|
||||||
}
|
}
|
||||||
|
@ -819,6 +819,7 @@ LayerManagerOGL::Render()
|
|||||||
|
|
||||||
if (mGLContext->IsDoubleBuffered()) {
|
if (mGLContext->IsDoubleBuffered()) {
|
||||||
mGLContext->SwapBuffers();
|
mGLContext->SwapBuffers();
|
||||||
|
LayerManager::PostPresent();
|
||||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -774,7 +774,7 @@ struct ParamTraits<LogData> {
|
|||||||
int type;
|
int type;
|
||||||
bool result =
|
bool result =
|
||||||
ReadParam(m, iter, &r->channel) &&
|
ReadParam(m, iter, &r->channel) &&
|
||||||
ReadParam(m, iter, &r->routing_id);
|
ReadParam(m, iter, &r->routing_id) &&
|
||||||
ReadParam(m, iter, &type) &&
|
ReadParam(m, iter, &type) &&
|
||||||
ReadParam(m, iter, &r->flags) &&
|
ReadParam(m, iter, &r->flags) &&
|
||||||
ReadParam(m, iter, &r->sent) &&
|
ReadParam(m, iter, &r->sent) &&
|
||||||
|
8
js/src/jit-test/tests/basic/write-frozen-property.js
Normal file
8
js/src/jit-test/tests/basic/write-frozen-property.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
function foo(x) {
|
||||||
|
x.a = 10;
|
||||||
|
assertEq(x.a, 0);
|
||||||
|
}
|
||||||
|
x = {a:0,b:1};
|
||||||
|
Object.freeze(x);
|
||||||
|
foo(x);
|
@ -1912,7 +1912,7 @@ obj_keys(JSContext *cx, uintN argc, Value *vp)
|
|||||||
for (size_t i = 0, len = props.length(); i < len; i++) {
|
for (size_t i = 0, len = props.length(); i < len; i++) {
|
||||||
jsid id = props[i];
|
jsid id = props[i];
|
||||||
if (JSID_IS_STRING(id)) {
|
if (JSID_IS_STRING(id)) {
|
||||||
JS_ALWAYS_TRUE(vals.append(StringValue(JSID_TO_STRING(id))));
|
vals.infallibleAppend(StringValue(JSID_TO_STRING(id)));
|
||||||
} else if (JSID_IS_INT(id)) {
|
} else if (JSID_IS_INT(id)) {
|
||||||
JSString *str = js_IntToString(cx, JSID_TO_INT(id));
|
JSString *str = js_IntToString(cx, JSID_TO_INT(id));
|
||||||
if (!str)
|
if (!str)
|
||||||
@ -1924,7 +1924,7 @@ obj_keys(JSContext *cx, uintN argc, Value *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(props.length() <= UINT32_MAX);
|
JS_ASSERT(props.length() <= UINT32_MAX);
|
||||||
JSObject *aobj = NewDenseCopiedArray(cx, jsuint(vals.length()), vals.begin());
|
JSObject *aobj = NewDenseCopiedArray(cx, uint32_t(vals.length()), vals.begin());
|
||||||
if (!aobj)
|
if (!aobj)
|
||||||
return false;
|
return false;
|
||||||
vp->setObject(*aobj);
|
vp->setObject(*aobj);
|
||||||
@ -2698,6 +2698,15 @@ obj_preventExtensions(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return obj->preventExtensions(cx, &props);
|
return obj->preventExtensions(cx, &props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ inline uintN
|
||||||
|
JSObject::getSealedOrFrozenAttributes(uintN attrs, ImmutabilityType it)
|
||||||
|
{
|
||||||
|
/* Make all attributes permanent; if freezing, make data attributes read-only. */
|
||||||
|
if (it == FREEZE && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
|
||||||
|
return JSPROP_PERMANENT | JSPROP_READONLY;
|
||||||
|
return JSPROP_PERMANENT;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
|
JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
|
||||||
{
|
{
|
||||||
@ -2718,27 +2727,62 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
|
|||||||
/* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
|
/* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
|
||||||
JS_ASSERT(!self->isDenseArray());
|
JS_ASSERT(!self->isDenseArray());
|
||||||
|
|
||||||
for (size_t i = 0, len = props.length(); i < len; i++) {
|
if (isNative() && !inDictionaryMode()) {
|
||||||
jsid id = props[i];
|
/*
|
||||||
|
* Seal/freeze non-dictionary objects by constructing a new shape
|
||||||
uintN attrs;
|
* hierarchy mirroring the original one, which can be shared if many
|
||||||
if (!self->getGenericAttributes(cx, id, &attrs))
|
* objects with the same structure are sealed/frozen. If we use the
|
||||||
|
* generic path below then any non-empty object will be converted to
|
||||||
|
* dictionary mode.
|
||||||
|
*/
|
||||||
|
Shape *last = EmptyShape::getInitialShape(cx, self->getClass(),
|
||||||
|
self->getProto(),
|
||||||
|
self->getParent(),
|
||||||
|
self->getAllocKind(),
|
||||||
|
self->lastProperty()->getObjectFlags());
|
||||||
|
if (!last)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Make all attributes permanent; if freezing, make data attributes read-only. */
|
/* Get an in order list of the shapes in this object. */
|
||||||
uintN new_attrs;
|
AutoShapeVector shapes(cx);
|
||||||
if (it == FREEZE && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
|
for (Shape::Range r = self->lastProperty()->all(); !r.empty(); r.popFront()) {
|
||||||
new_attrs = JSPROP_PERMANENT | JSPROP_READONLY;
|
if (!shapes.append(&r.front()))
|
||||||
else
|
return false;
|
||||||
new_attrs = JSPROP_PERMANENT;
|
}
|
||||||
|
Reverse(shapes.begin(), shapes.end());
|
||||||
|
|
||||||
/* If we already have the attributes we need, skip the setAttributes call. */
|
for (size_t i = 0; i < shapes.length(); i++) {
|
||||||
if ((attrs | new_attrs) == attrs)
|
StackShape child(shapes[i]);
|
||||||
continue;
|
child.attrs |= getSealedOrFrozenAttributes(child.attrs, it);
|
||||||
|
|
||||||
attrs |= new_attrs;
|
if (!JSID_IS_EMPTY(child.propid))
|
||||||
if (!self->setGenericAttributes(cx, id, &attrs))
|
MarkTypePropertyConfigured(cx, self, child.propid);
|
||||||
return false;
|
|
||||||
|
last = JS_PROPERTY_TREE(cx).getChild(cx, last, self->numFixedSlots(), child);
|
||||||
|
if (!last)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_ASSERT(self->lastProperty()->slotSpan() == last->slotSpan());
|
||||||
|
JS_ALWAYS_TRUE(setLastProperty(cx, last));
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < props.length(); i++) {
|
||||||
|
jsid id = props[i];
|
||||||
|
|
||||||
|
uintN attrs;
|
||||||
|
if (!self->getGenericAttributes(cx, id, &attrs))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uintN new_attrs = getSealedOrFrozenAttributes(attrs, it);
|
||||||
|
|
||||||
|
/* If we already have the attributes we need, skip the setAttributes call. */
|
||||||
|
if ((attrs | new_attrs) == attrs)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
attrs |= new_attrs;
|
||||||
|
if (!self->setGenericAttributes(cx, id, &attrs))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -968,6 +968,8 @@ struct JSObject : js::gc::Cell
|
|||||||
|
|
||||||
bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp);
|
bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp);
|
||||||
|
|
||||||
|
static inline uintN getSealedOrFrozenAttributes(uintN attrs, ImmutabilityType it);
|
||||||
|
|
||||||
inline void *&privateRef(uint32_t nfixed) const;
|
inline void *&privateRef(uint32_t nfixed) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -300,7 +300,6 @@ JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp
|
|||||||
{
|
{
|
||||||
JS_ASSERT(nativeContains(cx, shape));
|
JS_ASSERT(nativeContains(cx, shape));
|
||||||
JS_ASSERT(shape.isMethod());
|
JS_ASSERT(shape.isMethod());
|
||||||
JS_ASSERT(shape.writable());
|
|
||||||
JS_ASSERT(shape.hasSlot());
|
JS_ASSERT(shape.hasSlot());
|
||||||
JS_ASSERT(shape.hasDefaultSetter());
|
JS_ASSERT(shape.hasDefaultSetter());
|
||||||
JS_ASSERT(!isGlobal()); /* i.e. we are not changing the global shape */
|
JS_ASSERT(!isGlobal()); /* i.e. we are not changing the global shape */
|
||||||
|
@ -1071,7 +1071,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
|
|||||||
RootObject selfRoot(cx, &self);
|
RootObject selfRoot(cx, &self);
|
||||||
RootShape newRoot(cx, &newShape);
|
RootShape newRoot(cx, &newShape);
|
||||||
if (!toDictionaryMode(cx))
|
if (!toDictionaryMode(cx))
|
||||||
return false;
|
return NULL;
|
||||||
oldShape = lastProperty();
|
oldShape = lastProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1080,7 +1080,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
|
|||||||
RootShape oldRoot(cx, &oldShape);
|
RootShape oldRoot(cx, &oldShape);
|
||||||
newShape = js_NewGCShape(cx);
|
newShape = js_NewGCShape(cx);
|
||||||
if (!newShape)
|
if (!newShape)
|
||||||
return false;
|
return NULL;
|
||||||
new (newShape) Shape(oldShape->base()->unowned(), 0);
|
new (newShape) Shape(oldShape->base()->unowned(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1916,7 +1916,7 @@ DoReplace(JSContext *cx, RegExpStatics *res, ReplaceData &rdata)
|
|||||||
dp++;
|
dp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JS_ALWAYS_TRUE(rdata.sb.append(cp, repstr->length() - (cp - bp)));
|
rdata.sb.infallibleAppend(cp, repstr->length() - (cp - bp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -882,8 +882,11 @@ FrameState::discardForJoin(RegisterAllocation *&alloc, uint32_t stackDepth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
regstate(reg).associate(fe, RematInfo::DATA);
|
regstate(reg).associate(fe, RematInfo::DATA);
|
||||||
if (!alloc->synced(reg))
|
if (!alloc->synced(reg)) {
|
||||||
fe->data.unsync();
|
fe->data.unsync();
|
||||||
|
if (!reg.isReg())
|
||||||
|
fe->type.unsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a->sp = a->spBase + stackDepth;
|
a->sp = a->spBase + stackDepth;
|
||||||
|
@ -5064,6 +5064,9 @@ ProcessArgs(JSContext *cx, JSObject *obj, OptionParser *op)
|
|||||||
if (op->getBoolOption('a'))
|
if (op->getBoolOption('a'))
|
||||||
JS_ToggleOptions(cx, JSOPTION_METHODJIT_ALWAYS);
|
JS_ToggleOptions(cx, JSOPTION_METHODJIT_ALWAYS);
|
||||||
|
|
||||||
|
if (op->getBoolOption('c'))
|
||||||
|
compileOnly = true;
|
||||||
|
|
||||||
if (op->getBoolOption('m')) {
|
if (op->getBoolOption('m')) {
|
||||||
enableMethodJit = true;
|
enableMethodJit = true;
|
||||||
JS_ToggleOptions(cx, JSOPTION_METHODJIT);
|
JS_ToggleOptions(cx, JSOPTION_METHODJIT);
|
||||||
@ -5331,6 +5334,7 @@ main(int argc, char **argv, char **envp)
|
|||||||
|| !op.addBoolOption('i', "shell", "Enter prompt after running code")
|
|| !op.addBoolOption('i', "shell", "Enter prompt after running code")
|
||||||
|| !op.addBoolOption('m', "methodjit", "Enable the JaegerMonkey method JIT")
|
|| !op.addBoolOption('m', "methodjit", "Enable the JaegerMonkey method JIT")
|
||||||
|| !op.addBoolOption('n', "typeinfer", "Enable type inference")
|
|| !op.addBoolOption('n', "typeinfer", "Enable type inference")
|
||||||
|
|| !op.addBoolOption('c', "compileonly", "Only compile, don't run (syntax checking mode)")
|
||||||
|| !op.addBoolOption('d', "debugjit", "Enable runtime debug mode for method JIT code")
|
|| !op.addBoolOption('d', "debugjit", "Enable runtime debug mode for method JIT code")
|
||||||
|| !op.addBoolOption('a', "always-mjit",
|
|| !op.addBoolOption('a', "always-mjit",
|
||||||
"Do not try to run in the interpreter before method jitting.")
|
"Do not try to run in the interpreter before method jitting.")
|
||||||
|
@ -437,6 +437,7 @@ abstract public class GeckoApp
|
|||||||
MenuItem share = aMenu.findItem(R.id.share);
|
MenuItem share = aMenu.findItem(R.id.share);
|
||||||
MenuItem agentMode = aMenu.findItem(R.id.agent_mode);
|
MenuItem agentMode = aMenu.findItem(R.id.agent_mode);
|
||||||
MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
|
MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
|
||||||
|
MenuItem downloads = aMenu.findItem(R.id.downloads);
|
||||||
|
|
||||||
if (tab == null) {
|
if (tab == null) {
|
||||||
bookmark.setEnabled(false);
|
bookmark.setEnabled(false);
|
||||||
@ -453,11 +454,9 @@ abstract public class GeckoApp
|
|||||||
if (tab.isBookmark()) {
|
if (tab.isBookmark()) {
|
||||||
bookmark.setChecked(true);
|
bookmark.setChecked(true);
|
||||||
bookmark.setIcon(R.drawable.ic_menu_bookmark_remove);
|
bookmark.setIcon(R.drawable.ic_menu_bookmark_remove);
|
||||||
bookmark.setTitle(R.string.bookmark_remove);
|
|
||||||
} else {
|
} else {
|
||||||
bookmark.setChecked(false);
|
bookmark.setChecked(false);
|
||||||
bookmark.setIcon(R.drawable.ic_menu_bookmark_add);
|
bookmark.setIcon(R.drawable.ic_menu_bookmark_add);
|
||||||
bookmark.setTitle(R.string.bookmark_add);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forward.setEnabled(tab.canDoForward());
|
forward.setEnabled(tab.canDoForward());
|
||||||
@ -473,6 +472,10 @@ abstract public class GeckoApp
|
|||||||
saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
|
saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
|
||||||
tab.getContentType().equals("application/vnd.mozilla.xul+xml")));
|
tab.getContentType().equals("application/vnd.mozilla.xul+xml")));
|
||||||
|
|
||||||
|
// DownloadManager support is tied to level 12 and higher
|
||||||
|
if (Build.VERSION.SDK_INT < 12)
|
||||||
|
downloads.setVisible(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,12 +501,10 @@ abstract public class GeckoApp
|
|||||||
tab.removeBookmark();
|
tab.removeBookmark();
|
||||||
Toast.makeText(this, R.string.bookmark_removed, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.bookmark_removed, Toast.LENGTH_SHORT).show();
|
||||||
item.setIcon(R.drawable.ic_menu_bookmark_add);
|
item.setIcon(R.drawable.ic_menu_bookmark_add);
|
||||||
item.setTitle(R.string.bookmark_add);
|
|
||||||
} else {
|
} else {
|
||||||
tab.addBookmark();
|
tab.addBookmark();
|
||||||
Toast.makeText(this, R.string.bookmark_added, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.bookmark_added, Toast.LENGTH_SHORT).show();
|
||||||
item.setIcon(R.drawable.ic_menu_bookmark_remove);
|
item.setIcon(R.drawable.ic_menu_bookmark_remove);
|
||||||
item.setTitle(R.string.bookmark_remove);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -533,6 +534,10 @@ abstract public class GeckoApp
|
|||||||
case R.id.addons:
|
case R.id.addons:
|
||||||
loadUrlInTab("about:addons");
|
loadUrlInTab("about:addons");
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.downloads:
|
||||||
|
intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
case R.id.agent_mode:
|
case R.id.agent_mode:
|
||||||
Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
||||||
if (selectedTab == null)
|
if (selectedTab == null)
|
||||||
@ -975,6 +980,13 @@ abstract public class GeckoApp
|
|||||||
String host = message.getString("host");
|
String host = message.getString("host");
|
||||||
JSONArray permissions = message.getJSONArray("permissions");
|
JSONArray permissions = message.getJSONArray("permissions");
|
||||||
showSiteSettingsDialog(host, permissions);
|
showSiteSettingsDialog(host, permissions);
|
||||||
|
} else if (event.equals("Downloads:Done")) {
|
||||||
|
String displayName = message.getString("displayName");
|
||||||
|
String path = message.getString("path");
|
||||||
|
String mimeType = message.getString("mimeType");
|
||||||
|
int size = message.getInt("size");
|
||||||
|
|
||||||
|
handleDownloadDone(displayName, path, mimeType, size);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||||
@ -1302,6 +1314,17 @@ abstract public class GeckoApp
|
|||||||
tabs.closeTab(tab);
|
tabs.closeTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleDownloadDone(String displayName, String path, String mimeType, int size) {
|
||||||
|
// DownloadManager.addCompletedDownload is supported in level 12 and higher
|
||||||
|
if (Build.VERSION.SDK_INT >= 12) {
|
||||||
|
DownloadManager dm = (DownloadManager) mAppContext.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
|
dm.addCompletedDownload(displayName, displayName,
|
||||||
|
false /* do not use media scanner */,
|
||||||
|
mimeType, path, size,
|
||||||
|
false /* no notification */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void addPluginView(final View view,
|
void addPluginView(final View view,
|
||||||
final double x, final double y,
|
final double x, final double y,
|
||||||
final double w, final double h) {
|
final double w, final double h) {
|
||||||
@ -1559,6 +1582,7 @@ abstract public class GeckoApp
|
|||||||
GeckoAppShell.registerGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
|
GeckoAppShell.registerGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
|
||||||
GeckoAppShell.registerGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
|
GeckoAppShell.registerGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
|
||||||
GeckoAppShell.registerGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
GeckoAppShell.registerGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
||||||
|
GeckoAppShell.registerGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
|
||||||
|
|
||||||
mConnectivityFilter = new IntentFilter();
|
mConnectivityFilter = new IntentFilter();
|
||||||
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||||
@ -1794,6 +1818,7 @@ abstract public class GeckoApp
|
|||||||
GeckoAppShell.unregisterGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
|
GeckoAppShell.unregisterGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
|
||||||
GeckoAppShell.unregisterGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
|
GeckoAppShell.unregisterGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
|
||||||
GeckoAppShell.unregisterGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
GeckoAppShell.unregisterGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
||||||
|
GeckoAppShell.unregisterGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
|
||||||
|
|
||||||
mFavicons.close();
|
mFavicons.close();
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.gfx.IntSize;
|
||||||
import org.mozilla.gecko.gfx.ViewportMetrics;
|
import org.mozilla.gecko.gfx.ViewportMetrics;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
import android.app.*;
|
import android.app.*;
|
||||||
@ -78,6 +79,7 @@ public class GeckoEvent {
|
|||||||
public static final int ACTIVITY_START = 17;
|
public static final int ACTIVITY_START = 17;
|
||||||
public static final int BROADCAST = 19;
|
public static final int BROADCAST = 19;
|
||||||
public static final int VIEWPORT = 20;
|
public static final int VIEWPORT = 20;
|
||||||
|
public static final int TILE_SIZE = 21;
|
||||||
|
|
||||||
public static final int IME_COMPOSITION_END = 0;
|
public static final int IME_COMPOSITION_END = 0;
|
||||||
public static final int IME_COMPOSITION_BEGIN = 1;
|
public static final int IME_COMPOSITION_BEGIN = 1;
|
||||||
@ -228,6 +230,16 @@ public class GeckoEvent {
|
|||||||
mP1 = new Point(screenw, screenh);
|
mP1 = new Point(screenw, screenh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GeckoEvent(int etype, IntSize size) {
|
||||||
|
if (etype != TILE_SIZE) {
|
||||||
|
mType = INVALID;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mType = etype;
|
||||||
|
mP0 = new Point(size.width, size.height);
|
||||||
|
}
|
||||||
|
|
||||||
public GeckoEvent(String subject, String data) {
|
public GeckoEvent(String subject, String data) {
|
||||||
mType = BROADCAST;
|
mType = BROADCAST;
|
||||||
mCharacters = subject;
|
mCharacters = subject;
|
||||||
|
@ -107,6 +107,7 @@ JAVAFILES = \
|
|||||||
gfx/LayerController.java \
|
gfx/LayerController.java \
|
||||||
gfx/LayerRenderer.java \
|
gfx/LayerRenderer.java \
|
||||||
gfx/LayerView.java \
|
gfx/LayerView.java \
|
||||||
|
gfx/MultiTileLayer.java \
|
||||||
gfx/NinePatchTileLayer.java \
|
gfx/NinePatchTileLayer.java \
|
||||||
gfx/PanningPerfAPI.java \
|
gfx/PanningPerfAPI.java \
|
||||||
gfx/PlaceholderLayerClient.java \
|
gfx/PlaceholderLayerClient.java \
|
||||||
|
@ -43,8 +43,8 @@ import org.mozilla.gecko.gfx.IntSize;
|
|||||||
import org.mozilla.gecko.gfx.LayerClient;
|
import org.mozilla.gecko.gfx.LayerClient;
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
import org.mozilla.gecko.gfx.LayerController;
|
||||||
import org.mozilla.gecko.gfx.LayerRenderer;
|
import org.mozilla.gecko.gfx.LayerRenderer;
|
||||||
|
import org.mozilla.gecko.gfx.MultiTileLayer;
|
||||||
import org.mozilla.gecko.gfx.PointUtils;
|
import org.mozilla.gecko.gfx.PointUtils;
|
||||||
import org.mozilla.gecko.gfx.SingleTileLayer;
|
|
||||||
import org.mozilla.gecko.gfx.WidgetTileLayer;
|
import org.mozilla.gecko.gfx.WidgetTileLayer;
|
||||||
import org.mozilla.gecko.FloatUtils;
|
import org.mozilla.gecko.FloatUtils;
|
||||||
import org.mozilla.gecko.GeckoApp;
|
import org.mozilla.gecko.GeckoApp;
|
||||||
@ -53,6 +53,7 @@ import org.mozilla.gecko.GeckoEvent;
|
|||||||
import org.mozilla.gecko.GeckoEventListener;
|
import org.mozilla.gecko.GeckoEventListener;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@ -84,6 +85,8 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
|
|
||||||
private CairoImage mCairoImage;
|
private CairoImage mCairoImage;
|
||||||
|
|
||||||
|
private static final IntSize TILE_SIZE = new IntSize(256, 256);
|
||||||
|
|
||||||
private static final long MIN_VIEWPORT_CHANGE_DELAY = 350L;
|
private static final long MIN_VIEWPORT_CHANGE_DELAY = 350L;
|
||||||
private long mLastViewportChangeTime;
|
private long mLastViewportChangeTime;
|
||||||
private boolean mPendingViewportAdjust;
|
private boolean mPendingViewportAdjust;
|
||||||
@ -112,7 +115,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
public int getFormat() { return mFormat; }
|
public int getFormat() { return mFormat; }
|
||||||
};
|
};
|
||||||
|
|
||||||
mTileLayer = new SingleTileLayer(mCairoImage);
|
mTileLayer = new MultiTileLayer(mCairoImage, TILE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -143,6 +146,14 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateAndDraw", this);
|
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateAndDraw", this);
|
||||||
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this);
|
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this);
|
||||||
|
|
||||||
|
// This needs to happen before a call to sendResizeEventIfNecessary
|
||||||
|
// happens, but only needs to be called once. As that is only called by
|
||||||
|
// the layer controller or this, here is a safe place to do so.
|
||||||
|
if (mTileLayer instanceof MultiTileLayer) {
|
||||||
|
GeckoEvent event = new GeckoEvent(GeckoEvent.TILE_SIZE, TILE_SIZE);
|
||||||
|
GeckoAppShell.sendEventToGecko(event);
|
||||||
|
}
|
||||||
|
|
||||||
sendResizeEventIfNecessary();
|
sendResizeEventIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,8 +224,8 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
mUpdateViewportOnEndDraw = false;
|
mUpdateViewportOnEndDraw = false;
|
||||||
Rect rect = new Rect(x, y, x + width, y + height);
|
Rect rect = new Rect(x, y, x + width, y + height);
|
||||||
|
|
||||||
if (mTileLayer instanceof SingleTileLayer)
|
if (mTileLayer instanceof MultiTileLayer)
|
||||||
((SingleTileLayer)mTileLayer).invalidate(rect);
|
((MultiTileLayer)mTileLayer).invalidate(rect);
|
||||||
} finally {
|
} finally {
|
||||||
endTransaction(mTileLayer);
|
endTransaction(mTileLayer);
|
||||||
}
|
}
|
||||||
@ -228,6 +239,33 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyPixelsFromMultiTileLayer(Bitmap target) {
|
||||||
|
Canvas c = new Canvas(target);
|
||||||
|
ByteBuffer tileBuffer = mBuffer.slice();
|
||||||
|
int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8;
|
||||||
|
|
||||||
|
for (int y = 0; y < mBufferSize.height; y += TILE_SIZE.height) {
|
||||||
|
for (int x = 0; x < mBufferSize.width; x += TILE_SIZE.width) {
|
||||||
|
// Calculate tile size
|
||||||
|
IntSize tileSize = new IntSize(Math.min(mBufferSize.width - x, TILE_SIZE.width),
|
||||||
|
Math.min(mBufferSize.height - y, TILE_SIZE.height));
|
||||||
|
|
||||||
|
// Create a Bitmap from this tile
|
||||||
|
Bitmap tile = Bitmap.createBitmap(tileSize.width, tileSize.height,
|
||||||
|
CairoUtils.cairoFormatTobitmapConfig(mFormat));
|
||||||
|
tile.copyPixelsFromBuffer(tileBuffer.asIntBuffer());
|
||||||
|
|
||||||
|
// Copy the tile to the master Bitmap and recycle it
|
||||||
|
c.drawBitmap(tile, x, y, null);
|
||||||
|
tile.recycle();
|
||||||
|
|
||||||
|
// Progress the buffer to the next tile
|
||||||
|
tileBuffer.position(tileSize.getArea() * bpp);
|
||||||
|
tileBuffer = tileBuffer.slice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Bitmap getBitmap() {
|
public Bitmap getBitmap() {
|
||||||
// Begin a tile transaction, otherwise the buffer can be destroyed while
|
// Begin a tile transaction, otherwise the buffer can be destroyed while
|
||||||
// we're reading from it.
|
// we're reading from it.
|
||||||
@ -238,7 +276,12 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
try {
|
try {
|
||||||
Bitmap b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
|
Bitmap b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
|
||||||
CairoUtils.cairoFormatTobitmapConfig(mFormat));
|
CairoUtils.cairoFormatTobitmapConfig(mFormat));
|
||||||
b.copyPixelsFromBuffer(mBuffer.asIntBuffer());
|
|
||||||
|
if (mTileLayer instanceof MultiTileLayer)
|
||||||
|
copyPixelsFromMultiTileLayer(b);
|
||||||
|
else
|
||||||
|
b.copyPixelsFromBuffer(mBuffer.asIntBuffer());
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
} catch (OutOfMemoryError oom) {
|
} catch (OutOfMemoryError oom) {
|
||||||
Log.w(LOGTAG, "Unable to create bitmap", oom);
|
Log.w(LOGTAG, "Unable to create bitmap", oom);
|
||||||
@ -280,15 +323,25 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
|||||||
}
|
}
|
||||||
|
|
||||||
mScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
|
mScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
|
||||||
int maxSize = getLayerController().getView().getMaxTextureSize();
|
IntSize bufferSize;
|
||||||
|
|
||||||
// XXX Introduce tiling to solve this?
|
// Round up depending on layer implementation to remove texture wastage
|
||||||
if (mScreenSize.width > maxSize || mScreenSize.height > maxSize)
|
if (mTileLayer instanceof MultiTileLayer) {
|
||||||
throw new RuntimeException("Screen size of " + mScreenSize + " larger than maximum texture size of " + maxSize);
|
// Round to the next multiple of the tile size, respecting maximum texture size
|
||||||
|
bufferSize = new IntSize(((mScreenSize.width + LayerController.MIN_BUFFER.width - 1) / TILE_SIZE.width + 1) * TILE_SIZE.width,
|
||||||
|
((mScreenSize.height + LayerController.MIN_BUFFER.height - 1) / TILE_SIZE.height + 1) * TILE_SIZE.height);
|
||||||
|
|
||||||
// Round to next power of two until we use NPOT texture support
|
} else {
|
||||||
IntSize bufferSize = new IntSize(Math.min(maxSize, IntSize.nextPowerOfTwo(mScreenSize.width + LayerController.MIN_BUFFER.width)),
|
int maxSize = getLayerController().getView().getMaxTextureSize();
|
||||||
Math.min(maxSize, IntSize.nextPowerOfTwo(mScreenSize.height + LayerController.MIN_BUFFER.height)));
|
|
||||||
|
// XXX Integrate gralloc/tiling work to circumvent this
|
||||||
|
if (mScreenSize.width > maxSize || mScreenSize.height > maxSize)
|
||||||
|
throw new RuntimeException("Screen size of " + mScreenSize + " larger than maximum texture size of " + maxSize);
|
||||||
|
|
||||||
|
// Round to next power of two until we have NPOT texture support
|
||||||
|
bufferSize = new IntSize(Math.min(maxSize, IntSize.nextPowerOfTwo(mScreenSize.width + LayerController.MIN_BUFFER.width)),
|
||||||
|
Math.min(maxSize, IntSize.nextPowerOfTwo(mScreenSize.height + LayerController.MIN_BUFFER.height)));
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(LOGTAG, "Screen-size changed to " + mScreenSize);
|
Log.i(LOGTAG, "Screen-size changed to " + mScreenSize);
|
||||||
GeckoEvent event = new GeckoEvent(GeckoEvent.SIZE_CHANGED,
|
GeckoEvent event = new GeckoEvent(GeckoEvent.SIZE_CHANGED,
|
||||||
|
@ -61,8 +61,11 @@ public abstract class Layer {
|
|||||||
mResolution = 1.0f;
|
mResolution = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the layer. */
|
/**
|
||||||
public final void update(GL10 gl) {
|
* Updates the layer. This returns false if there is still work to be done
|
||||||
|
* after this update.
|
||||||
|
*/
|
||||||
|
public final boolean update(GL10 gl, RenderContext context) {
|
||||||
if (mTransactionLock.isHeldByCurrentThread()) {
|
if (mTransactionLock.isHeldByCurrentThread()) {
|
||||||
throw new RuntimeException("draw() called while transaction lock held by this " +
|
throw new RuntimeException("draw() called while transaction lock held by this " +
|
||||||
"thread?!");
|
"thread?!");
|
||||||
@ -70,11 +73,13 @@ public abstract class Layer {
|
|||||||
|
|
||||||
if (mTransactionLock.tryLock()) {
|
if (mTransactionLock.tryLock()) {
|
||||||
try {
|
try {
|
||||||
performUpdates(gl);
|
return performUpdates(gl, context);
|
||||||
} finally {
|
} finally {
|
||||||
mTransactionLock.unlock();
|
mTransactionLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Subclasses override this function to draw the layer. */
|
/** Subclasses override this function to draw the layer. */
|
||||||
@ -158,9 +163,10 @@ public abstract class Layer {
|
|||||||
/**
|
/**
|
||||||
* Subclasses may override this method to perform custom layer updates. This will be called
|
* Subclasses may override this method to perform custom layer updates. This will be called
|
||||||
* with the transaction lock held. Subclass implementations of this method must call the
|
* with the transaction lock held. Subclass implementations of this method must call the
|
||||||
* superclass implementation.
|
* superclass implementation. Returns false if there is still work to be done after this
|
||||||
|
* update is complete.
|
||||||
*/
|
*/
|
||||||
protected void performUpdates(GL10 gl) {
|
protected boolean performUpdates(GL10 gl, RenderContext context) {
|
||||||
if (mNewOrigin != null) {
|
if (mNewOrigin != null) {
|
||||||
mOrigin = mNewOrigin;
|
mOrigin = mNewOrigin;
|
||||||
mNewOrigin = null;
|
mNewOrigin = null;
|
||||||
@ -169,6 +175,8 @@ public abstract class Layer {
|
|||||||
mResolution = mNewResolution;
|
mResolution = mNewResolution;
|
||||||
mNewResolution = 0.0f;
|
mNewResolution = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RenderContext {
|
public static class RenderContext {
|
||||||
|
@ -147,6 +147,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
|||||||
LayerController controller = mView.getController();
|
LayerController controller = mView.getController();
|
||||||
RenderContext screenContext = createScreenContext();
|
RenderContext screenContext = createScreenContext();
|
||||||
|
|
||||||
|
boolean updated = true;
|
||||||
|
|
||||||
synchronized (controller) {
|
synchronized (controller) {
|
||||||
Layer rootLayer = controller.getRoot();
|
Layer rootLayer = controller.getRoot();
|
||||||
RenderContext pageContext = createPageContext();
|
RenderContext pageContext = createPageContext();
|
||||||
@ -166,12 +168,12 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
|||||||
mLastPageContext = pageContext;
|
mLastPageContext = pageContext;
|
||||||
|
|
||||||
/* Update layers. */
|
/* Update layers. */
|
||||||
if (rootLayer != null) rootLayer.update(gl);
|
if (rootLayer != null) updated &= rootLayer.update(gl, pageContext);
|
||||||
mShadowLayer.update(gl);
|
updated &= mShadowLayer.update(gl, pageContext);
|
||||||
mCheckerboardLayer.update(gl);
|
updated &= mCheckerboardLayer.update(gl, screenContext);
|
||||||
mFrameRateLayer.update(gl);
|
updated &= mFrameRateLayer.update(gl, screenContext);
|
||||||
mVertScrollLayer.update(gl);
|
updated &= mVertScrollLayer.update(gl, pageContext);
|
||||||
mHorizScrollLayer.update(gl);
|
updated &= mHorizScrollLayer.update(gl, pageContext);
|
||||||
|
|
||||||
/* Draw the background. */
|
/* Draw the background. */
|
||||||
gl.glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.0f);
|
gl.glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.0f);
|
||||||
@ -220,6 +222,10 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a layer update requires further work, schedule another redraw
|
||||||
|
if (!updated)
|
||||||
|
mView.requestRender();
|
||||||
|
|
||||||
PanningPerfAPI.recordFrameTime();
|
PanningPerfAPI.recordFrameTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
284
mobile/android/base/gfx/MultiTileLayer.java
Normal file
284
mobile/android/base/gfx/MultiTileLayer.java
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Android code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011-2012
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Chris Lord <chrislord.net@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.gfx;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.gfx.CairoImage;
|
||||||
|
import org.mozilla.gecko.gfx.IntSize;
|
||||||
|
import org.mozilla.gecko.gfx.SingleTileLayer;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.util.Log;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the logic needed to draw a layer made of multiple tiles.
|
||||||
|
*
|
||||||
|
* TODO: Support repeating.
|
||||||
|
*/
|
||||||
|
public class MultiTileLayer extends Layer {
|
||||||
|
private static final String LOGTAG = "GeckoMultiTileLayer";
|
||||||
|
|
||||||
|
private final CairoImage mImage;
|
||||||
|
private IntSize mTileSize;
|
||||||
|
private IntSize mBufferSize;
|
||||||
|
private final ArrayList<SingleTileLayer> mTiles;
|
||||||
|
|
||||||
|
public MultiTileLayer(CairoImage image, IntSize tileSize) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
mImage = image;
|
||||||
|
mTileSize = tileSize;
|
||||||
|
mBufferSize = new IntSize(0, 0);
|
||||||
|
mTiles = new ArrayList<SingleTileLayer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate(Rect dirtyRect) {
|
||||||
|
if (!inTransaction())
|
||||||
|
throw new RuntimeException("invalidate() is only valid inside a transaction");
|
||||||
|
|
||||||
|
int x = 0, y = 0;
|
||||||
|
IntSize size = getSize();
|
||||||
|
for (SingleTileLayer layer : mTiles) {
|
||||||
|
Rect tileRect = new Rect(x, y, x + mTileSize.width, y + mTileSize.height);
|
||||||
|
|
||||||
|
if (tileRect.intersect(dirtyRect)) {
|
||||||
|
tileRect.offset(-x, -y);
|
||||||
|
layer.invalidate(tileRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
x += mTileSize.width;
|
||||||
|
if (x >= size.width) {
|
||||||
|
x = 0;
|
||||||
|
y += mTileSize.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate() {
|
||||||
|
for (SingleTileLayer layer : mTiles)
|
||||||
|
layer.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntSize getSize() {
|
||||||
|
return mImage.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateTiles() {
|
||||||
|
IntSize size = getSize();
|
||||||
|
|
||||||
|
if (size.equals(mBufferSize))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Regenerate tiles
|
||||||
|
mTiles.clear();
|
||||||
|
int offset = 0;
|
||||||
|
final int format = mImage.getFormat();
|
||||||
|
final ByteBuffer buffer = mImage.getBuffer().slice();
|
||||||
|
final int bpp = CairoUtils.bitsPerPixelForCairoFormat(format) / 8;
|
||||||
|
for (int y = 0; y < size.height; y += mTileSize.height) {
|
||||||
|
for (int x = 0; x < size.width; x += mTileSize.width) {
|
||||||
|
// Create a CairoImage implementation that returns a
|
||||||
|
// tile from the parent CairoImage. It's assumed that
|
||||||
|
// the tiles are stored in series.
|
||||||
|
final IntSize layerSize =
|
||||||
|
new IntSize(Math.min(mTileSize.width, size.width - x),
|
||||||
|
Math.min(mTileSize.height, size.height - y));
|
||||||
|
final int tileOffset = offset;
|
||||||
|
|
||||||
|
CairoImage subImage = new CairoImage() {
|
||||||
|
@Override
|
||||||
|
public ByteBuffer getBuffer() {
|
||||||
|
// Create a ByteBuffer that shares the data of the original
|
||||||
|
// buffer, but is positioned and limited so that only the
|
||||||
|
// tile data is accessible.
|
||||||
|
buffer.position(tileOffset);
|
||||||
|
ByteBuffer tileBuffer = buffer.slice();
|
||||||
|
tileBuffer.limit(layerSize.getArea() * bpp);
|
||||||
|
|
||||||
|
return tileBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntSize getSize() {
|
||||||
|
return layerSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mTiles.add(new SingleTileLayer(subImage));
|
||||||
|
offset += layerSize.getArea() * bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set tile origins and resolution
|
||||||
|
refreshTileMetrics(getOrigin(), getResolution(), false);
|
||||||
|
|
||||||
|
mBufferSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean performUpdates(GL10 gl, RenderContext context) {
|
||||||
|
super.performUpdates(gl, context);
|
||||||
|
|
||||||
|
validateTiles();
|
||||||
|
|
||||||
|
// Iterate over the tiles and decide which ones we'll be drawing
|
||||||
|
int dirtyTiles = 0;
|
||||||
|
boolean screenUpdateDone = false;
|
||||||
|
SingleTileLayer firstDirtyTile = null;
|
||||||
|
for (SingleTileLayer layer : mTiles) {
|
||||||
|
// First do a non-texture update to make sure coordinates are
|
||||||
|
// up-to-date.
|
||||||
|
boolean invalid = layer.getSkipTextureUpdate();
|
||||||
|
layer.setSkipTextureUpdate(true);
|
||||||
|
layer.performUpdates(gl, context);
|
||||||
|
|
||||||
|
RectF layerBounds = layer.getBounds(context, new FloatSize(layer.getSize()));
|
||||||
|
boolean isDirty = layer.isDirty();
|
||||||
|
|
||||||
|
if (isDirty) {
|
||||||
|
if (!RectF.intersects(layerBounds, context.viewport)) {
|
||||||
|
if (firstDirtyTile == null)
|
||||||
|
firstDirtyTile = layer;
|
||||||
|
dirtyTiles ++;
|
||||||
|
invalid = true;
|
||||||
|
} else {
|
||||||
|
// This tile intersects with the screen and is dirty,
|
||||||
|
// update it immediately.
|
||||||
|
layer.setSkipTextureUpdate(false);
|
||||||
|
screenUpdateDone = true;
|
||||||
|
layer.performUpdates(gl, context);
|
||||||
|
invalid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use the SkipTextureUpdate flag as a marker of a tile's
|
||||||
|
// validity. This is required, as sometimes layers are drawn
|
||||||
|
// without updating first, and we mustn't draw tiles that have
|
||||||
|
// been marked as invalid that we haven't updated.
|
||||||
|
layer.setSkipTextureUpdate(invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now if no tiles that intersect with the screen were updated, update
|
||||||
|
// a single tile that doesn't (if there are any). This has the effect
|
||||||
|
// of spreading out non-critical texture upload over time, and smoothing
|
||||||
|
// upload-related hitches.
|
||||||
|
if (!screenUpdateDone && firstDirtyTile != null) {
|
||||||
|
firstDirtyTile.setSkipTextureUpdate(false);
|
||||||
|
firstDirtyTile.performUpdates(gl, context);
|
||||||
|
dirtyTiles --;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dirtyTiles == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshTileMetrics(Point origin, float resolution, boolean inTransaction) {
|
||||||
|
int x = 0, y = 0;
|
||||||
|
IntSize size = getSize();
|
||||||
|
for (SingleTileLayer layer : mTiles) {
|
||||||
|
if (!inTransaction)
|
||||||
|
layer.beginTransaction(null);
|
||||||
|
|
||||||
|
if (origin != null)
|
||||||
|
layer.setOrigin(new Point(origin.x + x, origin.y + y));
|
||||||
|
if (resolution >= 0.0f)
|
||||||
|
layer.setResolution(resolution);
|
||||||
|
|
||||||
|
if (!inTransaction)
|
||||||
|
layer.endTransaction();
|
||||||
|
|
||||||
|
x += mTileSize.width;
|
||||||
|
if (x >= size.width) {
|
||||||
|
x = 0;
|
||||||
|
y += mTileSize.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOrigin(Point newOrigin) {
|
||||||
|
super.setOrigin(newOrigin);
|
||||||
|
refreshTileMetrics(newOrigin, -1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResolution(float newResolution) {
|
||||||
|
super.setResolution(newResolution);
|
||||||
|
refreshTileMetrics(null, newResolution, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginTransaction(LayerView aView) {
|
||||||
|
super.beginTransaction(aView);
|
||||||
|
|
||||||
|
for (SingleTileLayer layer : mTiles)
|
||||||
|
layer.beginTransaction(aView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endTransaction() {
|
||||||
|
for (SingleTileLayer layer : mTiles)
|
||||||
|
layer.endTransaction();
|
||||||
|
|
||||||
|
super.endTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(RenderContext context) {
|
||||||
|
for (SingleTileLayer layer : mTiles) {
|
||||||
|
// We use the SkipTextureUpdate flag as a validity flag. If it's false,
|
||||||
|
// the contents of this tile are invalid and we shouldn't draw it.
|
||||||
|
if (layer.getSkipTextureUpdate())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Avoid work, only draw tiles that intersect with the viewport
|
||||||
|
RectF layerBounds = layer.getBounds(context, new FloatSize(layer.getSize()));
|
||||||
|
if (RectF.intersects(layerBounds, context.viewport))
|
||||||
|
layer.draw(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,12 +59,14 @@ public abstract class TileLayer extends Layer {
|
|||||||
private final CairoImage mImage;
|
private final CairoImage mImage;
|
||||||
private final boolean mRepeat;
|
private final boolean mRepeat;
|
||||||
private IntSize mSize;
|
private IntSize mSize;
|
||||||
|
private boolean mSkipTextureUpdate;
|
||||||
private int[] mTextureIDs;
|
private int[] mTextureIDs;
|
||||||
|
|
||||||
public TileLayer(boolean repeat, CairoImage image) {
|
public TileLayer(boolean repeat, CairoImage image) {
|
||||||
mRepeat = repeat;
|
mRepeat = repeat;
|
||||||
mImage = image;
|
mImage = image;
|
||||||
mSize = new IntSize(0, 0);
|
mSize = new IntSize(0, 0);
|
||||||
|
mSkipTextureUpdate = false;
|
||||||
|
|
||||||
IntSize bufferSize = mImage.getSize();
|
IntSize bufferSize = mImage.getSize();
|
||||||
mDirtyRect = new Rect();
|
mDirtyRect = new Rect();
|
||||||
@ -98,6 +100,10 @@ public abstract class TileLayer extends Layer {
|
|||||||
invalidate(new Rect(0, 0, bufferSize.width, bufferSize.height));
|
invalidate(new Rect(0, 0, bufferSize.width, bufferSize.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDirty() {
|
||||||
|
return mImage.getSize().isPositive() && (mTextureIDs == null || !mDirtyRect.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
private void validateTexture(GL10 gl) {
|
private void validateTexture(GL10 gl) {
|
||||||
/* Calculate the ideal texture size. This must be a power of two if
|
/* Calculate the ideal texture size. This must be a power of two if
|
||||||
* the texture is repeated or OpenGL ES 2.0 isn't supported, as
|
* the texture is repeated or OpenGL ES 2.0 isn't supported, as
|
||||||
@ -126,16 +132,28 @@ public abstract class TileLayer extends Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Tells the tile not to update the texture on the next update. */
|
||||||
|
public void setSkipTextureUpdate(boolean skip) {
|
||||||
|
mSkipTextureUpdate = skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSkipTextureUpdate() {
|
||||||
|
return mSkipTextureUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void performUpdates(GL10 gl) {
|
protected boolean performUpdates(GL10 gl, RenderContext context) {
|
||||||
super.performUpdates(gl);
|
super.performUpdates(gl, context);
|
||||||
|
|
||||||
|
if (mSkipTextureUpdate)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Reallocate the texture if the size has changed
|
// Reallocate the texture if the size has changed
|
||||||
validateTexture(gl);
|
validateTexture(gl);
|
||||||
|
|
||||||
// Don't do any work if the image has an invalid size.
|
// Don't do any work if the image has an invalid size.
|
||||||
if (!mImage.getSize().isPositive())
|
if (!mImage.getSize().isPositive())
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
// If we haven't allocated a texture, assume the whole region is dirty
|
// If we haven't allocated a texture, assume the whole region is dirty
|
||||||
if (mTextureIDs == null)
|
if (mTextureIDs == null)
|
||||||
@ -144,6 +162,8 @@ public abstract class TileLayer extends Layer {
|
|||||||
uploadDirtyRect(gl, mDirtyRect);
|
uploadDirtyRect(gl, mDirtyRect);
|
||||||
|
|
||||||
mDirtyRect.setEmpty();
|
mDirtyRect.setEmpty();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uploadFullTexture(GL10 gl) {
|
private void uploadFullTexture(GL10 gl) {
|
||||||
|
@ -77,8 +77,8 @@ public class WidgetTileLayer extends Layer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void performUpdates(GL10 gl) {
|
protected boolean performUpdates(GL10 gl, RenderContext context) {
|
||||||
super.performUpdates(gl);
|
super.performUpdates(gl, context);
|
||||||
|
|
||||||
if (mTextureIDs == null) {
|
if (mTextureIDs == null) {
|
||||||
mTextureIDs = new int[1];
|
mTextureIDs = new int[1];
|
||||||
@ -87,6 +87,8 @@ public class WidgetTileLayer extends Layer {
|
|||||||
|
|
||||||
bindAndSetGLParameters();
|
bindAndSetGLParameters();
|
||||||
GeckoAppShell.bindWidgetTexture();
|
GeckoAppShell.bindWidgetTexture();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,9 +27,7 @@
|
|||||||
|
|
||||||
<!ENTITY awesomebar_default_text "Enter Search or Address">
|
<!ENTITY awesomebar_default_text "Enter Search or Address">
|
||||||
|
|
||||||
<!ENTITY bookmarks_title "Bookmarks">
|
<!ENTITY bookmark "Bookmark">
|
||||||
<!ENTITY bookmark_add "Bookmark">
|
|
||||||
<!ENTITY bookmark_remove "Remove">
|
|
||||||
<!ENTITY bookmark_added "Bookmark added">
|
<!ENTITY bookmark_added "Bookmark added">
|
||||||
<!ENTITY bookmark_removed "Bookmark removed">
|
<!ENTITY bookmark_removed "Bookmark removed">
|
||||||
|
|
||||||
@ -72,6 +70,7 @@
|
|||||||
<!ENTITY quit "Quit">
|
<!ENTITY quit "Quit">
|
||||||
|
|
||||||
<!ENTITY addons "Add-ons">
|
<!ENTITY addons "Add-ons">
|
||||||
|
<!ENTITY downloads "Downloads">
|
||||||
|
|
||||||
<!ENTITY share "Share">
|
<!ENTITY share "Share">
|
||||||
<!ENTITY save_as_pdf "Save as PDF">
|
<!ENTITY save_as_pdf "Save as PDF">
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<item android:id="@+id/bookmark"
|
<item android:id="@+id/bookmark"
|
||||||
android:icon="@drawable/ic_menu_bookmark_add"
|
android:icon="@drawable/ic_menu_bookmark_add"
|
||||||
android:title="@string/bookmark_add"/>
|
android:title="@string/bookmark"/>
|
||||||
|
|
||||||
<item android:id="@+id/share"
|
<item android:id="@+id/share"
|
||||||
android:icon="@drawable/ic_menu_share"
|
android:icon="@drawable/ic_menu_share"
|
||||||
@ -33,6 +33,9 @@
|
|||||||
<item android:id="@+id/addons"
|
<item android:id="@+id/addons"
|
||||||
android:title="@string/addons"/>
|
android:title="@string/addons"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/downloads"
|
||||||
|
android:title="@string/downloads"/>
|
||||||
|
|
||||||
<item android:id="@+id/quit"
|
<item android:id="@+id/quit"
|
||||||
android:title="@string/quit" />
|
android:title="@string/quit" />
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -35,9 +35,7 @@
|
|||||||
<string name="awesomebar_default_text">&awesomebar_default_text;</string>
|
<string name="awesomebar_default_text">&awesomebar_default_text;</string>
|
||||||
|
|
||||||
<string name="quit">&quit;</string>
|
<string name="quit">&quit;</string>
|
||||||
<string name="bookmarks_title">&bookmarks_title;</string>
|
<string name="bookmark">&bookmark;</string>
|
||||||
<string name="bookmark_add">&bookmark_add;</string>
|
|
||||||
<string name="bookmark_remove">&bookmark_remove;</string>
|
|
||||||
<string name="bookmark_added">&bookmark_added;</string>
|
<string name="bookmark_added">&bookmark_added;</string>
|
||||||
<string name="bookmark_removed">&bookmark_removed;</string>
|
<string name="bookmark_removed">&bookmark_removed;</string>
|
||||||
|
|
||||||
@ -80,6 +78,7 @@
|
|||||||
<string name="forward">&forward;</string>
|
<string name="forward">&forward;</string>
|
||||||
<string name="new_tab">&new_tab;</string>
|
<string name="new_tab">&new_tab;</string>
|
||||||
<string name="addons">&addons;</string>
|
<string name="addons">&addons;</string>
|
||||||
|
<string name="downloads">&downloads;</string>
|
||||||
|
|
||||||
<string name="site_settings_title">&site_settings_title;</string>
|
<string name="site_settings_title">&site_settings_title;</string>
|
||||||
<string name="site_settings_cancel">&site_settings_cancel;</string>
|
<string name="site_settings_cancel">&site_settings_cancel;</string>
|
||||||
|
@ -5,6 +5,7 @@ import com.jayway.android.robotium.solo.Solo;
|
|||||||
import @ANDROID_PACKAGE_NAME@.*;
|
import @ANDROID_PACKAGE_NAME@.*;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.Instrumentation;
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -47,7 +48,7 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
|
|||||||
mActivity = getActivity();
|
mActivity = getActivity();
|
||||||
|
|
||||||
// Set up Robotium.solo and Driver objects
|
// Set up Robotium.solo and Driver objects
|
||||||
mSolo = new Solo(getInstrumentation(), getActivity());
|
mSolo = new Solo(getInstrumentation());
|
||||||
mDriver = new FennecNativeDriver(mActivity, mSolo);
|
mDriver = new FennecNativeDriver(mActivity, mSolo);
|
||||||
mActions = new FennecNativeActions(mActivity, mSolo, getInstrumentation());
|
mActions = new FennecNativeActions(mActivity, mSolo, getInstrumentation());
|
||||||
mDriver.setLogFile((String)config.get("logfile"));
|
mDriver.setLogFile((String)config.get("logfile"));
|
||||||
@ -67,30 +68,42 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
|
|||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final Activity getActivityFromClick(Element element) {
|
||||||
|
Instrumentation inst = getInstrumentation();
|
||||||
|
Instrumentation.ActivityMonitor monitor = inst.addMonitor((String)null, null, false);
|
||||||
|
element.click();
|
||||||
|
return inst.waitForMonitor(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
protected final void enterUrl(String url) {
|
protected final void enterUrl(String url) {
|
||||||
mActions.waitForGeckoEvent("Gecko:Ready");
|
mActions.expectGeckoEvent("Gecko:Ready").blockForEvent();
|
||||||
Element awesomebar = mDriver.findElement("awesome_bar");
|
Element awesomebar = mDriver.findElement(mActivity, "awesome_bar");
|
||||||
awesomebar.click();
|
Activity awesomeBarActivity = getActivityFromClick(awesomebar);
|
||||||
getInstrumentation().waitForIdleSync();
|
getInstrumentation().waitForIdleSync();
|
||||||
|
|
||||||
Element urlbar = mDriver.findElement("awesomebar_text");
|
Element urlbar = mDriver.findElement(awesomeBarActivity, "awesomebar_text");
|
||||||
mActions.sendKeys(url);
|
mActions.sendKeys(url);
|
||||||
mAsserter.is(urlbar.getText(), url, "Awesomebar URL typed properly");
|
mAsserter.is(urlbar.getText(), url, "Awesomebar URL typed properly");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void loadUrl(String url) {
|
protected final void hitEnterAndWait() {
|
||||||
enterUrl(url);
|
Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
|
||||||
|
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
|
mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
|
||||||
// wait for screen to load
|
// wait for screen to load
|
||||||
mActions.waitForGeckoEvent("DOMContentLoaded");
|
contentEventExpecter.blockForEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void loadUrl(String url) {
|
||||||
|
enterUrl(url);
|
||||||
|
hitEnterAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void verifyUrl(String url) {
|
protected final void verifyUrl(String url) {
|
||||||
Element awesomebar = mDriver.findElement("awesome_bar");
|
Element awesomebar = mDriver.findElement(mActivity, "awesome_bar");
|
||||||
Element urlbar = mDriver.findElement("awesomebar_text");
|
Activity awesomeBarActivity = getActivityFromClick(awesomebar);
|
||||||
awesomebar.click();
|
|
||||||
getInstrumentation().waitForIdleSync();
|
getInstrumentation().waitForIdleSync();
|
||||||
|
|
||||||
|
Element urlbar = mDriver.findElement(awesomeBarActivity, "awesomebar_text");
|
||||||
mAsserter.is(urlbar.getText(), url, "Awesomebar URL stayed the same");
|
mAsserter.is(urlbar.getText(), url, "Awesomebar URL stayed the same");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,7 @@ public class testBookmark extends BaseTest {
|
|||||||
|
|
||||||
//Click the top item in the list.
|
//Click the top item in the list.
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
|
mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
|
hitEnterAndWait();
|
||||||
mActions.waitForGeckoEvent("DOMContentLoaded");
|
|
||||||
|
|
||||||
verifyUrl(URL);
|
verifyUrl(URL);
|
||||||
|
|
||||||
@ -23,8 +22,8 @@ public class testBookmark extends BaseTest {
|
|||||||
getInstrumentation().waitForIdleSync();
|
getInstrumentation().waitForIdleSync();
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
|
mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
|
mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
|
|
||||||
mActions.waitForGeckoEvent("DOMContentLoaded");
|
hitEnterAndWait();
|
||||||
|
|
||||||
getInstrumentation().waitForIdleSync();
|
getInstrumentation().waitForIdleSync();
|
||||||
//Unfortunately, the item isn't constant so can't be tested.
|
//Unfortunately, the item isn't constant so can't be tested.
|
||||||
|
@ -2,36 +2,31 @@
|
|||||||
package @ANDROID_PACKAGE_NAME@.tests;
|
package @ANDROID_PACKAGE_NAME@.tests;
|
||||||
|
|
||||||
import @ANDROID_PACKAGE_NAME@.*;
|
import @ANDROID_PACKAGE_NAME@.*;
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
public class testNewTab extends BaseTest {
|
public class testNewTab extends BaseTest {
|
||||||
public void testNewTab() {
|
public void testNewTab() {
|
||||||
// TODO: find a better way to not hardcode this url
|
// TODO: find a better way to not hardcode this url
|
||||||
String url = "http://mochi.test:8888/tests/robocop/robocop_blank_01.html";
|
String url = "http://mochi.test:8888/tests/robocop/robocop_blank_01.html";
|
||||||
String url2 = "http://mochi.test:8888/tests/robocop/robocop_blank_02.html";
|
String url2 = "http://mochi.test:8888/tests/robocop/robocop_blank_02.html";
|
||||||
mActions.waitForGeckoEvent("Gecko:Ready");
|
mActions.expectGeckoEvent("Gecko:Ready").blockForEvent();
|
||||||
Element tabs = mDriver.findElement("tabs");
|
Element tabs = mDriver.findElement(getActivity(), "tabs");
|
||||||
// Add one tab
|
// Add one tab
|
||||||
tabs.click();
|
Activity awesomeBarActivity = getActivityFromClick(tabs);
|
||||||
|
|
||||||
Element urlbar = mDriver.findElement("awesomebar_text");
|
|
||||||
getInstrumentation().waitForIdleSync();
|
getInstrumentation().waitForIdleSync();
|
||||||
|
Element urlbar = mDriver.findElement(awesomeBarActivity, "awesomebar_text");
|
||||||
mActions.sendKeys(url);
|
mActions.sendKeys(url);
|
||||||
mAsserter.is(urlbar.getText(), url, "Awesomebar url is fine");
|
mAsserter.is(urlbar.getText(), url, "Awesomebar url is fine");
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
|
hitEnterAndWait();
|
||||||
mActions.waitForGeckoEvent("DOMContentLoaded");
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(5000);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// See tab count
|
// See tab count
|
||||||
Element tabCount = mDriver.findElement("tabs_count");
|
Element tabCount = mDriver.findElement(getActivity(), "tabs_count");
|
||||||
mAsserter.is(tabCount.getText(), "2", "Number of tabs has increased");
|
mAsserter.is(tabCount.getText(), "2", "Number of tabs has increased");
|
||||||
|
|
||||||
// Click tab list
|
// Click tab list
|
||||||
tabs.click();
|
Activity tabTray = getActivityFromClick(tabs);
|
||||||
Element addTab = mDriver.findElement("add_tab");
|
Element addTab = mDriver.findElement(tabTray, "add_tab");
|
||||||
|
|
||||||
//Add another tab
|
//Add another tab
|
||||||
addTab.click();
|
addTab.click();
|
||||||
@ -40,8 +35,7 @@ public class testNewTab extends BaseTest {
|
|||||||
getInstrumentation().waitForIdleSync();
|
getInstrumentation().waitForIdleSync();
|
||||||
mAsserter.is(urlbar.getText(), url2, "URL is still fine");
|
mAsserter.is(urlbar.getText(), url2, "URL is still fine");
|
||||||
|
|
||||||
mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
|
hitEnterAndWait();
|
||||||
mActions.waitForGeckoEvent("DOMContentLoaded");
|
|
||||||
//Check tab count another time.
|
//Check tab count another time.
|
||||||
mAsserter.is(tabCount.getText(), "3", "Number of tabs has increased");
|
mAsserter.is(tabCount.getText(), "3", "Number of tabs has increased");
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ var Downloads = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
observe: function dl_observe(aSubject, aTopic, aData) {
|
observe: function dl_observe(aSubject, aTopic, aData) {
|
||||||
|
let download = aSubject.QueryInterface(Ci.nsIDownload);
|
||||||
let msgKey = "";
|
let msgKey = "";
|
||||||
if (aTopic == "dl-start") {
|
if (aTopic == "dl-start") {
|
||||||
msgKey = "alertDownloadsStart";
|
msgKey = "alertDownloadsStart";
|
||||||
@ -138,12 +139,21 @@ var Downloads = {
|
|||||||
NativeWindow.toast.show(Strings.browser.GetStringFromName("alertDownloadsToast"), "long");
|
NativeWindow.toast.show(Strings.browser.GetStringFromName("alertDownloadsToast"), "long");
|
||||||
} else if (aTopic == "dl-done") {
|
} else if (aTopic == "dl-done") {
|
||||||
msgKey = "alertDownloadsDone";
|
msgKey = "alertDownloadsDone";
|
||||||
|
|
||||||
|
let message = {
|
||||||
|
gecko: {
|
||||||
|
type: "Downloads:Done",
|
||||||
|
displayName: download.displayName,
|
||||||
|
path: download.targetFile.path,
|
||||||
|
size: download.size,
|
||||||
|
mimeType: download.MIMEInfo ? download.MIMEInfo.type : ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sendMessageToJava(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msgKey) {
|
if (msgKey)
|
||||||
let download = aSubject.QueryInterface(Ci.nsIDownload);
|
|
||||||
this.showAlert(download, Strings.browser.formatStringFromName(msgKey, [download.displayName], 1));
|
this.showAlert(download, Strings.browser.formatStringFromName(msgKey, [download.displayName], 1));
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
QueryInterface: function (aIID) {
|
QueryInterface: function (aIID) {
|
||||||
|
@ -7,9 +7,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||||||
|
|
||||||
|
|
||||||
function dump(a) {
|
function dump(a) {
|
||||||
Cc["@mozilla.org/consoleservice;1"]
|
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
|
||||||
.getService(Ci.nsIConsoleService)
|
|
||||||
.logStringMessage(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openWindow(aParent, aURL, aTarget, aFeatures, aArgs) {
|
function openWindow(aParent, aURL, aTarget, aFeatures, aArgs) {
|
||||||
@ -45,10 +43,7 @@ BrowserCLH.prototype = {
|
|||||||
let urlParam = "about:home";
|
let urlParam = "about:home";
|
||||||
try {
|
try {
|
||||||
urlParam = aCmdLine.handleFlagWithParam("remote", false);
|
urlParam = aCmdLine.handleFlagWithParam("remote", false);
|
||||||
} catch (e) {
|
} catch (e) { /* Optional */ }
|
||||||
// Optional so not a real error
|
|
||||||
}
|
|
||||||
dump("fs_handle: " + urlParam);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let uri = resolveURIInternal(aCmdLine, urlParam);
|
let uri = resolveURIInternal(aCmdLine, urlParam);
|
||||||
@ -57,19 +52,14 @@ BrowserCLH.prototype = {
|
|||||||
|
|
||||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
if (browserWin) {
|
if (browserWin) {
|
||||||
browserWin.browserDOMWindow.openURI(uri,
|
browserWin.browserDOMWindow.openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
|
||||||
null,
|
|
||||||
Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW,
|
|
||||||
Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
|
|
||||||
} else {
|
} else {
|
||||||
browserWin = openWindow(null, "chrome://browser/content/browser.xul", "_blank", "chrome,dialog=no,all", urlParam);
|
browserWin = openWindow(null, "chrome://browser/content/browser.xul", "_blank", "chrome,dialog=no,all", urlParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
aCmdLine.preventDefault = true;
|
aCmdLine.preventDefault = true;
|
||||||
} catch (x) {
|
} catch (x) {
|
||||||
Cc["@mozilla.org/consoleservice;1"]
|
dump("BrowserCLH.handle: " + x);
|
||||||
.getService(Ci.nsIConsoleService)
|
|
||||||
.logStringMessage("fs_handle exception!: " + x);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
137
netwerk/cache/nsCacheService.cpp
vendored
137
netwerk/cache/nsCacheService.cpp
vendored
@ -75,6 +75,7 @@
|
|||||||
#include "mozilla/Util.h" // for DebugOnly
|
#include "mozilla/Util.h" // for DebugOnly
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
|
|
||||||
#include "mozilla/FunctionTimer.h"
|
#include "mozilla/FunctionTimer.h"
|
||||||
|
|
||||||
@ -152,6 +153,7 @@ public:
|
|||||||
, mDiskCacheEnabled(false)
|
, mDiskCacheEnabled(false)
|
||||||
, mDiskCacheCapacity(0)
|
, mDiskCacheCapacity(0)
|
||||||
, mDiskCacheMaxEntrySize(-1) // -1 means "no limit"
|
, mDiskCacheMaxEntrySize(-1) // -1 means "no limit"
|
||||||
|
, mSmartSizeEnabled(false)
|
||||||
, mOfflineCacheEnabled(false)
|
, mOfflineCacheEnabled(false)
|
||||||
, mOfflineCacheCapacity(0)
|
, mOfflineCacheCapacity(0)
|
||||||
, mMemoryCacheEnabled(true)
|
, mMemoryCacheEnabled(true)
|
||||||
@ -175,6 +177,7 @@ public:
|
|||||||
void SetDiskCacheCapacity(PRInt32);
|
void SetDiskCacheCapacity(PRInt32);
|
||||||
PRInt32 DiskCacheMaxEntrySize() { return mDiskCacheMaxEntrySize; }
|
PRInt32 DiskCacheMaxEntrySize() { return mDiskCacheMaxEntrySize; }
|
||||||
nsILocalFile * DiskCacheParentDirectory() { return mDiskCacheParentDirectory; }
|
nsILocalFile * DiskCacheParentDirectory() { return mDiskCacheParentDirectory; }
|
||||||
|
bool SmartSizeEnabled() { return mSmartSizeEnabled; }
|
||||||
|
|
||||||
bool OfflineCacheEnabled();
|
bool OfflineCacheEnabled();
|
||||||
PRInt32 OfflineCacheCapacity() { return mOfflineCacheCapacity; }
|
PRInt32 OfflineCacheCapacity() { return mOfflineCacheCapacity; }
|
||||||
@ -199,6 +202,7 @@ private:
|
|||||||
PRInt32 mDiskCacheCapacity; // in kilobytes
|
PRInt32 mDiskCacheCapacity; // in kilobytes
|
||||||
PRInt32 mDiskCacheMaxEntrySize; // in kilobytes
|
PRInt32 mDiskCacheMaxEntrySize; // in kilobytes
|
||||||
nsCOMPtr<nsILocalFile> mDiskCacheParentDirectory;
|
nsCOMPtr<nsILocalFile> mDiskCacheParentDirectory;
|
||||||
|
bool mSmartSizeEnabled;
|
||||||
|
|
||||||
bool mOfflineCacheEnabled;
|
bool mOfflineCacheEnabled;
|
||||||
PRInt32 mOfflineCacheCapacity; // in kilobytes
|
PRInt32 mOfflineCacheCapacity; // in kilobytes
|
||||||
@ -218,6 +222,23 @@ private:
|
|||||||
|
|
||||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver)
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver)
|
||||||
|
|
||||||
|
class nsSetDiskSmartSizeCallback : public nsITimerCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
NS_IMETHOD Notify(nsITimer* aTimer) {
|
||||||
|
if (nsCacheService::gService) {
|
||||||
|
nsCacheServiceAutoLock autoLock;
|
||||||
|
nsCacheService::gService->SetDiskSmartSize_Locked();
|
||||||
|
nsCacheService::gService->mSmartSizeTimer = nsnull;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsSetDiskSmartSizeCallback, nsITimerCallback)
|
||||||
|
|
||||||
// Runnable sent to main thread after the cache IO thread calculates available
|
// Runnable sent to main thread after the cache IO thread calculates available
|
||||||
// disk space, so that there is no race in setting mDiskCacheCapacity.
|
// disk space, so that there is no race in setting mDiskCacheCapacity.
|
||||||
class nsSetSmartSizeEvent: public nsRunnable
|
class nsSetSmartSizeEvent: public nsRunnable
|
||||||
@ -228,32 +249,27 @@ public:
|
|||||||
|
|
||||||
NS_IMETHOD Run()
|
NS_IMETHOD Run()
|
||||||
{
|
{
|
||||||
nsresult rv;
|
|
||||||
NS_ASSERTION(NS_IsMainThread(),
|
NS_ASSERTION(NS_IsMainThread(),
|
||||||
"Setting smart size data off the main thread");
|
"Setting smart size data off the main thread");
|
||||||
|
|
||||||
// Main thread may have already called nsCacheService::Shutdown
|
// Main thread may have already called nsCacheService::Shutdown
|
||||||
if (!nsCacheService::gService || !nsCacheService::gService->mObserver)
|
if (!nsCacheService::gService || !nsCacheService::gService->mObserver)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
bool smartSizeEnabled;
|
// Ensure smart sizing wasn't switched off while event was pending.
|
||||||
nsCOMPtr<nsIPrefBranch2> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
// It is safe to access the observer without the lock since we are
|
||||||
if (!branch) {
|
// on the main thread and the value changes only on the main thread.
|
||||||
NS_WARNING("Failed to get pref service!");
|
if (!nsCacheService::gService->mObserver->SmartSizeEnabled())
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_OK;
|
||||||
}
|
|
||||||
// ensure smart sizing wasn't switched off while event was pending
|
nsCacheService::SetDiskCacheCapacity(mSmartSize);
|
||||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
|
||||||
&smartSizeEnabled);
|
nsCOMPtr<nsIPrefBranch2> ps = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||||
if (NS_FAILED(rv))
|
if (!ps ||
|
||||||
smartSizeEnabled = false;
|
NS_FAILED(ps->SetIntPref(DISK_CACHE_SMART_SIZE_PREF, mSmartSize)))
|
||||||
if (smartSizeEnabled) {
|
NS_WARNING("Failed to set smart size pref");
|
||||||
nsCacheService::SetDiskCacheCapacity(mSmartSize);
|
|
||||||
rv = branch->SetIntPref(DISK_CACHE_SMART_SIZE_PREF, mSmartSize);
|
return NS_OK;
|
||||||
if (NS_FAILED(rv))
|
|
||||||
NS_WARNING("Failed to set smart size pref");
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -445,13 +461,12 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject,
|
|||||||
// Update the cache capacity when smart sizing is turned on/off
|
// Update the cache capacity when smart sizing is turned on/off
|
||||||
} else if (!strcmp(DISK_CACHE_SMART_SIZE_ENABLED_PREF, data.get())) {
|
} else if (!strcmp(DISK_CACHE_SMART_SIZE_ENABLED_PREF, data.get())) {
|
||||||
// Is the update because smartsizing was turned on, or off?
|
// Is the update because smartsizing was turned on, or off?
|
||||||
bool smartSizeEnabled;
|
|
||||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||||
&smartSizeEnabled);
|
&mSmartSizeEnabled);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
PRInt32 newCapacity = 0;
|
PRInt32 newCapacity = 0;
|
||||||
if (smartSizeEnabled) {
|
if (mSmartSizeEnabled) {
|
||||||
nsCacheService::SetDiskSmartSize();
|
nsCacheService::SetDiskSmartSize();
|
||||||
} else {
|
} else {
|
||||||
// Smart sizing switched off: use user specified size
|
// Smart sizing switched off: use user specified size
|
||||||
@ -671,21 +686,22 @@ nsCacheProfilePrefObserver::PermittedToSmartSize(nsIPrefBranch* branch, bool
|
|||||||
// of 50 MB, then keep user's value. Otherwise use smart sizing.
|
// of 50 MB, then keep user's value. Otherwise use smart sizing.
|
||||||
rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &oldCapacity);
|
rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &oldCapacity);
|
||||||
if (oldCapacity < PRE_GECKO_2_0_DEFAULT_CACHE_SIZE) {
|
if (oldCapacity < PRE_GECKO_2_0_DEFAULT_CACHE_SIZE) {
|
||||||
branch->SetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
mSmartSizeEnabled = false;
|
||||||
false);
|
branch->SetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||||
return false;
|
mSmartSizeEnabled);
|
||||||
|
return mSmartSizeEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set manual setting to MAX cache size as starting val for any
|
// Set manual setting to MAX cache size as starting val for any
|
||||||
// adjustment by user: (bug 559942 comment 65)
|
// adjustment by user: (bug 559942 comment 65)
|
||||||
branch->SetIntPref(DISK_CACHE_CAPACITY_PREF, MAX_CACHE_SIZE);
|
branch->SetIntPref(DISK_CACHE_CAPACITY_PREF, MAX_CACHE_SIZE);
|
||||||
}
|
}
|
||||||
bool smartSizeEnabled;
|
|
||||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||||
&smartSizeEnabled);
|
&mSmartSizeEnabled);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return false;
|
mSmartSizeEnabled = false;
|
||||||
return !!smartSizeEnabled;
|
return mSmartSizeEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -758,20 +774,12 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch)
|
|||||||
if (PermittedToSmartSize(branch, firstSmartSizeRun)) {
|
if (PermittedToSmartSize(branch, firstSmartSizeRun)) {
|
||||||
// Avoid evictions: use previous cache size until smart size event
|
// Avoid evictions: use previous cache size until smart size event
|
||||||
// updates mDiskCacheCapacity
|
// updates mDiskCacheCapacity
|
||||||
if (!firstSmartSizeRun) {
|
rv = branch->GetIntPref(firstSmartSizeRun ?
|
||||||
PRInt32 oldSmartSize;
|
DISK_CACHE_CAPACITY_PREF :
|
||||||
rv = branch->GetIntPref(DISK_CACHE_SMART_SIZE_PREF,
|
DISK_CACHE_SMART_SIZE_PREF,
|
||||||
&oldSmartSize);
|
&mDiskCacheCapacity);
|
||||||
mDiskCacheCapacity = oldSmartSize;
|
if (NS_FAILED(rv))
|
||||||
} else {
|
mDiskCacheCapacity = DEFAULT_CACHE_SIZE;
|
||||||
PRInt32 oldCapacity;
|
|
||||||
rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &oldCapacity);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
mDiskCacheCapacity = oldCapacity;
|
|
||||||
} else {
|
|
||||||
mDiskCacheCapacity = DEFAULT_CACHE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstSmartSizeRun) {
|
if (firstSmartSizeRun) {
|
||||||
@ -1142,6 +1150,11 @@ nsCacheService::Shutdown()
|
|||||||
ClearDoomList();
|
ClearDoomList();
|
||||||
ClearActiveEntries();
|
ClearActiveEntries();
|
||||||
|
|
||||||
|
if (mSmartSizeTimer) {
|
||||||
|
mSmartSizeTimer->Cancel();
|
||||||
|
mSmartSizeTimer = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure to wait for any pending cache-operations before
|
// Make sure to wait for any pending cache-operations before
|
||||||
// proceeding with destructive actions (bug #620660)
|
// proceeding with destructive actions (bug #620660)
|
||||||
(void) SyncWithCacheIOThread();
|
(void) SyncWithCacheIOThread();
|
||||||
@ -1447,7 +1460,22 @@ nsCacheService::CreateDiskDevice()
|
|||||||
mDiskDevice = nsnull;
|
mDiskDevice = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDiskSmartSize_Locked(true);
|
// Disk device is usually created during the startup. Delay smart size
|
||||||
|
// calculation to avoid possible massive IO caused by eviction of entries
|
||||||
|
// in case the new smart size is smaller than current cache usage.
|
||||||
|
if (!mSmartSizeTimer) {
|
||||||
|
mSmartSizeTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = mSmartSizeTimer->InitWithCallback(new nsSetDiskSmartSizeCallback(),
|
||||||
|
1000*60*3,
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("Failed to post smart size timer");
|
||||||
|
mSmartSizeTimer = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2652,11 +2680,11 @@ nsCacheService::SetDiskSmartSize()
|
|||||||
|
|
||||||
if (!gService) return NS_ERROR_NOT_AVAILABLE;
|
if (!gService) return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
return gService->SetDiskSmartSize_Locked(false);
|
return gService->SetDiskSmartSize_Locked();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsCacheService::SetDiskSmartSize_Locked(bool checkPref)
|
nsCacheService::SetDiskSmartSize_Locked()
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
@ -2666,17 +2694,8 @@ nsCacheService::SetDiskSmartSize_Locked(bool checkPref)
|
|||||||
if (!mDiskDevice)
|
if (!mDiskDevice)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
if (checkPref) {
|
if (!mObserver->SmartSizeEnabled())
|
||||||
nsCOMPtr<nsIPrefBranch2> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
if (!branch) return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
bool smartSizeEnabled;
|
|
||||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
|
||||||
&smartSizeEnabled);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv) || !smartSizeEnabled)
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString cachePath;
|
nsAutoString cachePath;
|
||||||
rv = mObserver->DiskCacheParentDirectory()->GetPath(cachePath);
|
rv = mObserver->DiskCacheParentDirectory()->GetPath(cachePath);
|
||||||
|
5
netwerk/cache/nsCacheService.h
vendored
5
netwerk/cache/nsCacheService.h
vendored
@ -63,6 +63,7 @@ class nsDiskCacheDevice;
|
|||||||
class nsMemoryCacheDevice;
|
class nsMemoryCacheDevice;
|
||||||
class nsOfflineCacheDevice;
|
class nsOfflineCacheDevice;
|
||||||
class nsCacheServiceAutoLock;
|
class nsCacheServiceAutoLock;
|
||||||
|
class nsITimer;
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@ -196,6 +197,7 @@ private:
|
|||||||
friend class nsProcessRequestEvent;
|
friend class nsProcessRequestEvent;
|
||||||
friend class nsSetSmartSizeEvent;
|
friend class nsSetSmartSizeEvent;
|
||||||
friend class nsBlockOnCacheThreadEvent;
|
friend class nsBlockOnCacheThreadEvent;
|
||||||
|
friend class nsSetDiskSmartSizeCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal Methods
|
* Internal Methods
|
||||||
@ -264,7 +266,7 @@ private:
|
|||||||
void LogCacheStatistics();
|
void LogCacheStatistics();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsresult SetDiskSmartSize_Locked(bool checkPref);
|
nsresult SetDiskSmartSize_Locked();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data Members
|
* Data Members
|
||||||
@ -280,6 +282,7 @@ private:
|
|||||||
nsCOMPtr<nsIThread> mCacheIOThread;
|
nsCOMPtr<nsIThread> mCacheIOThread;
|
||||||
|
|
||||||
nsTArray<nsISupports*> mDoomedObjects;
|
nsTArray<nsISupports*> mDoomedObjects;
|
||||||
|
nsCOMPtr<nsITimer> mSmartSizeTimer;
|
||||||
|
|
||||||
bool mInitialized;
|
bool mInitialized;
|
||||||
|
|
||||||
|
26
netwerk/cache/nsDiskCacheDevice.cpp
vendored
26
netwerk/cache/nsDiskCacheDevice.cpp
vendored
@ -118,6 +118,22 @@ private:
|
|||||||
nsDiskCacheBinding *mBinding;
|
nsDiskCacheBinding *mBinding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class nsEvictDiskCacheEntriesEvent : public nsRunnable {
|
||||||
|
public:
|
||||||
|
nsEvictDiskCacheEntriesEvent(nsDiskCacheDevice *device)
|
||||||
|
: mDevice(device) {}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
nsCacheServiceAutoLock lock;
|
||||||
|
mDevice->EvictDiskCacheEntries(mDevice->mCacheCapacity);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsDiskCacheDevice *mDevice;
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* nsDiskCacheEvictor
|
* nsDiskCacheEvictor
|
||||||
*
|
*
|
||||||
@ -1120,8 +1136,14 @@ nsDiskCacheDevice::SetCapacity(PRUint32 capacity)
|
|||||||
// Units are KiB's
|
// Units are KiB's
|
||||||
mCacheCapacity = capacity;
|
mCacheCapacity = capacity;
|
||||||
if (Initialized()) {
|
if (Initialized()) {
|
||||||
// start evicting entries if the new size is smaller!
|
if (NS_IsMainThread()) {
|
||||||
EvictDiskCacheEntries(mCacheCapacity);
|
// Do not evict entries on the main thread
|
||||||
|
nsCacheService::DispatchToCacheIOThread(
|
||||||
|
new nsEvictDiskCacheEntriesEvent(this));
|
||||||
|
} else {
|
||||||
|
// start evicting entries if the new size is smaller!
|
||||||
|
EvictDiskCacheEntries(mCacheCapacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Let cache map know of the new capacity
|
// Let cache map know of the new capacity
|
||||||
mCacheMap.NotifyCapacityChange(capacity);
|
mCacheMap.NotifyCapacityChange(capacity);
|
||||||
|
1
netwerk/cache/nsDiskCacheDevice.h
vendored
1
netwerk/cache/nsDiskCacheDevice.h
vendored
@ -107,6 +107,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class nsDiskCacheDeviceDeactivateEntryEvent;
|
friend class nsDiskCacheDeviceDeactivateEntryEvent;
|
||||||
|
friend class nsEvictDiskCacheEntriesEvent;
|
||||||
/**
|
/**
|
||||||
* Private methods
|
* Private methods
|
||||||
*/
|
*/
|
||||||
|
@ -1017,7 +1017,7 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
|||||||
// Use write-ahead-logging for performance. We cap the autocheckpoint limit at
|
// Use write-ahead-logging for performance. We cap the autocheckpoint limit at
|
||||||
// 16 pages (around 500KB).
|
// 16 pages (around 500KB).
|
||||||
mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA journal_mode = WAL"));
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA journal_mode = WAL"));
|
||||||
mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA wal_autocheckpoint = 16"));
|
"PRAGMA wal_autocheckpoint = 16"));
|
||||||
|
|
||||||
|
@ -113,6 +113,8 @@ nsHttpPipeline::~nsHttpPipeline()
|
|||||||
// make sure we aren't still holding onto any transactions!
|
// make sure we aren't still holding onto any transactions!
|
||||||
Close(NS_ERROR_ABORT);
|
Close(NS_ERROR_ABORT);
|
||||||
|
|
||||||
|
NS_IF_RELEASE(mConnection);
|
||||||
|
|
||||||
if (mPushBackBuf)
|
if (mPushBackBuf)
|
||||||
free(mPushBackBuf);
|
free(mPushBackBuf);
|
||||||
}
|
}
|
||||||
@ -125,7 +127,7 @@ nsHttpPipeline::AddTransaction(nsAHttpTransaction *trans)
|
|||||||
NS_ADDREF(trans);
|
NS_ADDREF(trans);
|
||||||
mRequestQ.AppendElement(trans);
|
mRequestQ.AppendElement(trans);
|
||||||
|
|
||||||
if (mConnection) {
|
if (mConnection && !mClosed) {
|
||||||
trans->SetConnection(this);
|
trans->SetConnection(this);
|
||||||
|
|
||||||
if (mRequestQ.Length() == 1)
|
if (mRequestQ.Length() == 1)
|
||||||
@ -700,10 +702,6 @@ nsHttpPipeline::Close(nsresult reason)
|
|||||||
mResponseQ.Clear();
|
mResponseQ.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// we must no longer reference the connection! This needs to come
|
|
||||||
// after we've closed all our transactions, since they might want
|
|
||||||
// connection info as they close.
|
|
||||||
NS_IF_RELEASE(mConnection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -192,4 +192,9 @@ protected:
|
|||||||
nsCOMPtr<mozIStorageStatement> mStatement;
|
nsCOMPtr<mozIStorageStatement> mStatement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Use this to make queries uniquely identifiable in telemetry
|
||||||
|
// statistics, especially PRAGMAs. We don't include __LINE__ so that
|
||||||
|
// queries are stable in the face of source code changes.
|
||||||
|
#define MOZ_STORAGE_UNIQUIFY_QUERY_STR "/* " __FILE__ " */ "
|
||||||
|
|
||||||
#endif /* MOZSTORAGEHELPER_H */
|
#endif /* MOZSTORAGEHELPER_H */
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#include "mozIStorageAsyncStatement.h"
|
#include "mozIStorageAsyncStatement.h"
|
||||||
#include "mozIStoragePendingStatement.h"
|
#include "mozIStoragePendingStatement.h"
|
||||||
#include "mozIStorageError.h"
|
#include "mozIStorageError.h"
|
||||||
|
#include "mozStorageHelper.h"
|
||||||
|
|
||||||
#define OBSERVER_TOPIC_IDLE_DAILY "idle-daily"
|
#define OBSERVER_TOPIC_IDLE_DAILY "idle-daily"
|
||||||
#define OBSERVER_TOPIC_XPCOM_SHUTDOWN "xpcom-shutdown"
|
#define OBSERVER_TOPIC_XPCOM_SHUTDOWN "xpcom-shutdown"
|
||||||
@ -221,7 +222,7 @@ Vacuumer::execute()
|
|||||||
{
|
{
|
||||||
nsCOMPtr<mozIStorageStatement> stmt;
|
nsCOMPtr<mozIStorageStatement> stmt;
|
||||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA page_size"
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size"
|
||||||
), getter_AddRefs(stmt));
|
), getter_AddRefs(stmt));
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
bool hasResult;
|
bool hasResult;
|
||||||
@ -240,7 +241,7 @@ Vacuumer::execute()
|
|||||||
{
|
{
|
||||||
nsCOMPtr<mozIStorageStatement> stmt;
|
nsCOMPtr<mozIStorageStatement> stmt;
|
||||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA journal_mode"
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA journal_mode"
|
||||||
), getter_AddRefs(stmt));
|
), getter_AddRefs(stmt));
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
bool hasResult;
|
bool hasResult;
|
||||||
@ -300,7 +301,7 @@ Vacuumer::execute()
|
|||||||
if (canOptimizePageSize) {
|
if (canOptimizePageSize) {
|
||||||
nsCOMPtr<mozIStorageAsyncStatement> pageSizeStmt;
|
nsCOMPtr<mozIStorageAsyncStatement> pageSizeStmt;
|
||||||
rv = mDBConn->CreateAsyncStatement(nsPrintfCString(
|
rv = mDBConn->CreateAsyncStatement(nsPrintfCString(
|
||||||
"PRAGMA page_size = %ld", expectedPageSize
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size = %ld", expectedPageSize
|
||||||
), getter_AddRefs(pageSizeStmt));
|
), getter_AddRefs(pageSizeStmt));
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
nsCOMPtr<BaseCallback> callback = new BaseCallback();
|
nsCOMPtr<BaseCallback> callback = new BaseCallback();
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
#include "StorageBaseStatementInternal.h"
|
#include "StorageBaseStatementInternal.h"
|
||||||
#include "SQLCollations.h"
|
#include "SQLCollations.h"
|
||||||
#include "FileSystemModule.h"
|
#include "FileSystemModule.h"
|
||||||
|
#include "mozStorageHelper.h"
|
||||||
|
|
||||||
#include "prlog.h"
|
#include "prlog.h"
|
||||||
#include "prprf.h"
|
#include "prprf.h"
|
||||||
@ -650,14 +651,17 @@ Connection::initialize(nsIFile *aDatabaseFile,
|
|||||||
// the database has just been created, otherwise, if the database does not
|
// the database has just been created, otherwise, if the database does not
|
||||||
// use WAL journal mode, a VACUUM operation will updated its page_size.
|
// use WAL journal mode, a VACUUM operation will updated its page_size.
|
||||||
PRInt64 pageSize = DEFAULT_PAGE_SIZE;
|
PRInt64 pageSize = DEFAULT_PAGE_SIZE;
|
||||||
nsCAutoString pageSizeQuery("PRAGMA page_size = ");
|
nsCAutoString pageSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR
|
||||||
|
"PRAGMA page_size = ");
|
||||||
pageSizeQuery.AppendInt(pageSize);
|
pageSizeQuery.AppendInt(pageSize);
|
||||||
rv = ExecuteSimpleSQL(pageSizeQuery);
|
rv = ExecuteSimpleSQL(pageSizeQuery);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Get the current page_size, since it may differ from the specified value.
|
// Get the current page_size, since it may differ from the specified value.
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
srv = prepareStatement(NS_LITERAL_CSTRING("PRAGMA page_size"), &stmt);
|
NS_NAMED_LITERAL_CSTRING(pragma_page_size,
|
||||||
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size");
|
||||||
|
srv = prepareStatement(pragma_page_size, &stmt);
|
||||||
if (srv == SQLITE_OK) {
|
if (srv == SQLITE_OK) {
|
||||||
if (SQLITE_ROW == stepStatement(stmt)) {
|
if (SQLITE_ROW == stepStatement(stmt)) {
|
||||||
pageSize = ::sqlite3_column_int64(stmt, 0);
|
pageSize = ::sqlite3_column_int64(stmt, 0);
|
||||||
@ -668,7 +672,8 @@ Connection::initialize(nsIFile *aDatabaseFile,
|
|||||||
// Setting the cache_size forces the database open, verifying if it is valid
|
// Setting the cache_size forces the database open, verifying if it is valid
|
||||||
// or corrupt. So this is executed regardless it being actually needed.
|
// or corrupt. So this is executed regardless it being actually needed.
|
||||||
// The cache_size is calculated from the actual page_size, to save memory.
|
// The cache_size is calculated from the actual page_size, to save memory.
|
||||||
nsCAutoString cacheSizeQuery("PRAGMA cache_size = ");
|
nsCAutoString cacheSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR
|
||||||
|
"PRAGMA cache_size = ");
|
||||||
cacheSizeQuery.AppendInt(NS_MIN(DEFAULT_CACHE_SIZE_PAGES,
|
cacheSizeQuery.AppendInt(NS_MIN(DEFAULT_CACHE_SIZE_PAGES,
|
||||||
PRInt32(MAX_CACHE_SIZE_BYTES / pageSize)));
|
PRInt32(MAX_CACHE_SIZE_BYTES / pageSize)));
|
||||||
srv = ::sqlite3_exec(mDBConn, cacheSizeQuery.get(), NULL, NULL, NULL);
|
srv = ::sqlite3_exec(mDBConn, cacheSizeQuery.get(), NULL, NULL, NULL);
|
||||||
|
@ -798,11 +798,12 @@ toolbar#nav-bar {
|
|||||||
self.automation.log.warning("TEST-UNEXPECTED-FAIL | invalid setup: missing mochikit extension")
|
self.automation.log.warning("TEST-UNEXPECTED-FAIL | invalid setup: missing mochikit extension")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Support Firefox (browser) and SeaMonkey (navigator).
|
# Support Firefox (browser), B2G (shell) and SeaMonkey (navigator).
|
||||||
chrome = ""
|
chrome = ""
|
||||||
if options.browserChrome or options.chrome or options.a11y:
|
if options.browserChrome or options.chrome or options.a11y:
|
||||||
chrome += """
|
chrome += """
|
||||||
overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
|
overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||||
|
overlay chrome://browser/content/shell.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||||
overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
|
overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -280,6 +280,7 @@ class MochiRemote(Mochitest):
|
|||||||
def buildProfile(self, options):
|
def buildProfile(self, options):
|
||||||
manifest = Mochitest.buildProfile(self, options)
|
manifest = Mochitest.buildProfile(self, options)
|
||||||
self.localProfile = options.profilePath
|
self.localProfile = options.profilePath
|
||||||
|
self._dm.removeDir(self.remoteProfile)
|
||||||
if self._dm.pushDir(options.profilePath, self.remoteProfile) == None:
|
if self._dm.pushDir(options.profilePath, self.remoteProfile) == None:
|
||||||
raise devicemanager.FileError("Unable to copy profile to device.")
|
raise devicemanager.FileError("Unable to copy profile to device.")
|
||||||
|
|
||||||
|
@ -233,7 +233,8 @@ SetJournalMode(nsCOMPtr<mozIStorageConnection>& aDBConn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageStatement> statement;
|
nsCOMPtr<mozIStorageStatement> statement;
|
||||||
nsCAutoString query("PRAGMA journal_mode = ");
|
nsCAutoString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR
|
||||||
|
"PRAGMA journal_mode = ");
|
||||||
query.Append(journalMode);
|
query.Append(journalMode);
|
||||||
aDBConn->CreateStatement(query, getter_AddRefs(statement));
|
aDBConn->CreateStatement(query, getter_AddRefs(statement));
|
||||||
NS_ENSURE_TRUE(statement, JOURNAL_DELETE);
|
NS_ENSURE_TRUE(statement, JOURNAL_DELETE);
|
||||||
@ -551,7 +552,7 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
|||||||
// database file already existed with a different page size.
|
// database file already existed with a different page size.
|
||||||
nsCOMPtr<mozIStorageStatement> statement;
|
nsCOMPtr<mozIStorageStatement> statement;
|
||||||
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA page_size"
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size"
|
||||||
), getter_AddRefs(statement));
|
), getter_AddRefs(statement));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
bool hasResult = false;
|
bool hasResult = false;
|
||||||
@ -563,7 +564,7 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
|||||||
|
|
||||||
// Ensure that temp tables are held in memory, not on disk.
|
// Ensure that temp tables are held in memory, not on disk.
|
||||||
nsresult rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
nsresult rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"PRAGMA temp_store = MEMORY"));
|
MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA temp_store = MEMORY"));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Get the current database size. Due to chunked growth we have to use
|
// Get the current database size. Due to chunked growth we have to use
|
||||||
@ -593,7 +594,8 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
|||||||
// Set the number of cached pages.
|
// Set the number of cached pages.
|
||||||
// We don't use PRAGMA default_cache_size, since the database could be moved
|
// We don't use PRAGMA default_cache_size, since the database could be moved
|
||||||
// among different devices and the value would adapt accordingly.
|
// among different devices and the value would adapt accordingly.
|
||||||
nsCAutoString cacheSizePragma("PRAGMA cache_size = ");
|
nsCAutoString cacheSizePragma(MOZ_STORAGE_UNIQUIFY_QUERY_STR
|
||||||
|
"PRAGMA cache_size = ");
|
||||||
cacheSizePragma.AppendInt(cacheSize / mDBPageSize);
|
cacheSizePragma.AppendInt(cacheSize / mDBPageSize);
|
||||||
rv = mMainConn->ExecuteSimpleSQL(cacheSizePragma);
|
rv = mMainConn->ExecuteSimpleSQL(cacheSizePragma);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
@ -908,11 +908,11 @@ let PlacesDBUtils = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
PLACES_DATABASE_PAGESIZE_B: "PRAGMA page_size",
|
PLACES_DATABASE_PAGESIZE_B: "PRAGMA page_size /* PlacesDBUtils.jsm PAGESIZE_B */",
|
||||||
|
|
||||||
PLACES_DATABASE_SIZE_PER_PAGE_B: function() {
|
PLACES_DATABASE_SIZE_PER_PAGE_B: function() {
|
||||||
// Cannot use the filesize here, due to chunked growth.
|
// Cannot use the filesize here, due to chunked growth.
|
||||||
let stmt = DBConn.createStatement("PRAGMA page_size");
|
let stmt = DBConn.createStatement("PRAGMA page_size /* PlacesDBUtils.jsm SIZE_PER_PAGE_B */");
|
||||||
stmt.executeStep();
|
stmt.executeStep();
|
||||||
let pageSize = stmt.row.page_size;
|
let pageSize = stmt.row.page_size;
|
||||||
stmt.finalize();
|
stmt.finalize();
|
||||||
|
@ -3126,7 +3126,8 @@ nsUrlClassifierDBServiceWorker::SetCacheSize(
|
|||||||
NS_ASSERTION(hasResult, "Should always be able to get page size from sqlite");
|
NS_ASSERTION(hasResult, "Should always be able to get page size from sqlite");
|
||||||
PRUint32 pageSize = mGetPageSizeStatement->AsInt32(0);
|
PRUint32 pageSize = mGetPageSizeStatement->AsInt32(0);
|
||||||
PRUint32 cachePages = aCacheSize / pageSize;
|
PRUint32 cachePages = aCacheSize / pageSize;
|
||||||
nsCAutoString cacheSizePragma("PRAGMA cache_size=");
|
nsCAutoString cacheSizePragma(MOZ_STORAGE_UNIQUIFY_QUERY_STR
|
||||||
|
"PRAGMA cache_size=");
|
||||||
cacheSizePragma.AppendInt(cachePages);
|
cacheSizePragma.AppendInt(cachePages);
|
||||||
rv = aConnection->ExecuteSimpleSQL(cacheSizePragma);
|
rv = aConnection->ExecuteSimpleSQL(cacheSizePragma);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
@ -3413,7 +3414,7 @@ nsUrlClassifierDBServiceWorker::OpenDb()
|
|||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = connection->CreateStatement
|
rv = connection->CreateStatement
|
||||||
(NS_LITERAL_CSTRING("PRAGMA page_size"),
|
(NS_LITERAL_CSTRING(MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size"),
|
||||||
getter_AddRefs(mGetPageSizeStatement));
|
getter_AddRefs(mGetPageSizeStatement));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
@ -1279,8 +1279,20 @@
|
|||||||
var self = this;
|
var self = this;
|
||||||
this.muteButton.addEventListener("command", function() { self.toggleMute(); }, false);
|
this.muteButton.addEventListener("command", function() { self.toggleMute(); }, false);
|
||||||
this.playButton.addEventListener("command", function() { self.togglePause(); }, false);
|
this.playButton.addEventListener("command", function() { self.togglePause(); }, false);
|
||||||
this.controlsSpacer.addEventListener("click", function(e) { if (e.button == 0 && !self.hasError()) { self.togglePause(); } }, false);
|
|
||||||
this.fullscreenButton.addEventListener("command", function() { self.toggleFullscreen(); }, false );
|
this.fullscreenButton.addEventListener("command", function() { self.toggleFullscreen(); }, false );
|
||||||
|
|
||||||
|
this.controlsSpacer.addEventListener("click", function spacerClickHandler(e) {
|
||||||
|
if (e.button != 0 || self.hasError())
|
||||||
|
return;
|
||||||
|
// Read defaultPrevented asynchronously, since Web content
|
||||||
|
// may want to consume the "click" event but will only
|
||||||
|
// receive it after us (bug 693014).
|
||||||
|
setTimeout(function togglePauseCallback() {
|
||||||
|
if (!e.defaultPrevented)
|
||||||
|
self.togglePause();
|
||||||
|
}, 0);
|
||||||
|
}, false);
|
||||||
|
|
||||||
if (!this.isAudioOnly) {
|
if (!this.isAudioOnly) {
|
||||||
this.muteButton.addEventListener("mouseover", function(e) { self.onVolumeMouseInOut(e); }, false);
|
this.muteButton.addEventListener("mouseover", function(e) { self.onVolumeMouseInOut(e); }, false);
|
||||||
this.muteButton.addEventListener("mouseout", function(e) { self.onVolumeMouseInOut(e); }, false);
|
this.muteButton.addEventListener("mouseout", function(e) { self.onVolumeMouseInOut(e); }, false);
|
||||||
|
@ -823,9 +823,10 @@ var gViewController = {
|
|||||||
isEnabled: function(aAddon) {
|
isEnabled: function(aAddon) {
|
||||||
return !!aAddon && (gViewController.currentViewObj != gDetailView);
|
return !!aAddon && (gViewController.currentViewObj != gDetailView);
|
||||||
},
|
},
|
||||||
doCommand: function(aAddon) {
|
doCommand: function(aAddon, aScrollToPreferences) {
|
||||||
gViewController.loadView("addons://detail/" +
|
gViewController.loadView("addons://detail/" +
|
||||||
encodeURIComponent(aAddon.id));
|
encodeURIComponent(aAddon.id) +
|
||||||
|
(aScrollToPreferences ? "/preferences" : ""));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -964,7 +965,7 @@ var gViewController = {
|
|||||||
},
|
},
|
||||||
doCommand: function(aAddon) {
|
doCommand: function(aAddon) {
|
||||||
if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) {
|
if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) {
|
||||||
gViewController.commands.cmd_showItemDetails.doCommand(aAddon);
|
gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var optionsURL = aAddon.optionsURL;
|
var optionsURL = aAddon.optionsURL;
|
||||||
@ -2565,7 +2566,7 @@ var gDetailView = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateView: function(aAddon, aIsRemote) {
|
_updateView: function(aAddon, aIsRemote, aScrollToPreferences) {
|
||||||
this._updatePrefs.addObserver("", this, false);
|
this._updatePrefs.addObserver("", this, false);
|
||||||
this.clearLoading();
|
this.clearLoading();
|
||||||
|
|
||||||
@ -2738,7 +2739,7 @@ var gDetailView = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fillSettingsRows();
|
this.fillSettingsRows(aScrollToPreferences);
|
||||||
|
|
||||||
this.updateState();
|
this.updateState();
|
||||||
|
|
||||||
@ -2747,6 +2748,13 @@ var gDetailView = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
show: function(aAddonId, aRequest) {
|
show: function(aAddonId, aRequest) {
|
||||||
|
let index = aAddonId.indexOf("/preferences");
|
||||||
|
let scrollToPreferences = false;
|
||||||
|
if (index >= 0) {
|
||||||
|
aAddonId = aAddonId.substring(0, index);
|
||||||
|
scrollToPreferences = true;
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this._loadingTimer = setTimeout(function() {
|
this._loadingTimer = setTimeout(function() {
|
||||||
self.node.setAttribute("loading-extended", true);
|
self.node.setAttribute("loading-extended", true);
|
||||||
@ -2759,7 +2767,7 @@ var gDetailView = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (aAddon) {
|
if (aAddon) {
|
||||||
self._updateView(aAddon, false);
|
self._updateView(aAddon, false, scrollToPreferences);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2878,7 +2886,7 @@ var gDetailView = {
|
|||||||
rows.removeChild(rows.lastChild);
|
rows.removeChild(rows.lastChild);
|
||||||
},
|
},
|
||||||
|
|
||||||
fillSettingsRows: function () {
|
fillSettingsRows: function (aScrollToPreferences) {
|
||||||
this.emptySettingsRows();
|
this.emptySettingsRows();
|
||||||
if (this._addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE)
|
if (this._addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE)
|
||||||
return;
|
return;
|
||||||
@ -2952,11 +2960,31 @@ var gDetailView = {
|
|||||||
if (firstSetting)
|
if (firstSetting)
|
||||||
firstSetting.clientTop;
|
firstSetting.clientTop;
|
||||||
Services.obs.notifyObservers(document, "addon-options-displayed", gDetailView._addon.id);
|
Services.obs.notifyObservers(document, "addon-options-displayed", gDetailView._addon.id);
|
||||||
|
if (aScrollToPreferences)
|
||||||
|
gDetailView.scrollToPreferencesRows();
|
||||||
}, false);
|
}, false);
|
||||||
} else {
|
} else {
|
||||||
if (firstSetting)
|
if (firstSetting)
|
||||||
firstSetting.clientTop;
|
firstSetting.clientTop;
|
||||||
Services.obs.notifyObservers(document, "addon-options-displayed", this._addon.id);
|
Services.obs.notifyObservers(document, "addon-options-displayed", this._addon.id);
|
||||||
|
if (aScrollToPreferences)
|
||||||
|
gDetailView.scrollToPreferencesRows();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollToPreferencesRows: function() {
|
||||||
|
// We find this row, rather than remembering it from above,
|
||||||
|
// in case it has been changed by the observers.
|
||||||
|
let firstRow = gDetailView.node.querySelector('setting[first-row="true"]');
|
||||||
|
if (firstRow) {
|
||||||
|
let top = firstRow.boxObject.y;
|
||||||
|
top -= parseInt(window.getComputedStyle(firstRow, null).getPropertyValue("margin-top"));
|
||||||
|
|
||||||
|
let detailViewBoxObject = gDetailView.node.boxObject;
|
||||||
|
top -= detailViewBoxObject.y;
|
||||||
|
|
||||||
|
detailViewBoxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||||
|
detailViewBoxObject.scrollTo(0, top);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ var observer = {
|
|||||||
var setting = aSubject.querySelector("rows > setting[first-row] ~ setting");
|
var setting = aSubject.querySelector("rows > setting[first-row] ~ setting");
|
||||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "setting-label");
|
var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "setting-label");
|
||||||
isnot(input, null, "XBL binding should be applied");
|
isnot(input, null, "XBL binding should be applied");
|
||||||
|
|
||||||
|
// Add some extra height to the scrolling pane to ensure that it needs to scroll when appropriate.
|
||||||
|
gManagerWindow.document.getElementById("detail-controls").style.marginBottom = "1000px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -39,6 +42,17 @@ function installAddon(aCallback) {
|
|||||||
}, "application/x-xpinstall");
|
}, "application/x-xpinstall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkScrolling(aShouldHaveScrolled) {
|
||||||
|
var detailView = gManagerWindow.document.getElementById("detail-view");
|
||||||
|
var boxObject = detailView.boxObject;
|
||||||
|
boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||||
|
ok(detailView.scrollHeight > boxObject.height, "Page should require scrolling");
|
||||||
|
if (aShouldHaveScrolled)
|
||||||
|
isnot(detailView.scrollTop, 0, "Page should have scrolled");
|
||||||
|
else
|
||||||
|
is(detailView.scrollTop, 0, "Page should not have scrolled");
|
||||||
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
@ -147,14 +161,15 @@ add_test(function() {
|
|||||||
|
|
||||||
wait_for_view_load(gManagerWindow, function() {
|
wait_for_view_load(gManagerWindow, function() {
|
||||||
is(observer.lastData, "inlinesettings1@tests.mozilla.org", "Observer notification should have fired");
|
is(observer.lastData, "inlinesettings1@tests.mozilla.org", "Observer notification should have fired");
|
||||||
|
is(gManagerWindow.gViewController.currentViewId,
|
||||||
|
"addons://detail/inlinesettings1%40tests.mozilla.org/preferences",
|
||||||
|
"Current view should scroll to preferences");
|
||||||
|
checkScrolling(true);
|
||||||
|
|
||||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||||
var settings = grid.querySelectorAll("rows > setting");
|
var settings = grid.querySelectorAll("rows > setting");
|
||||||
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
||||||
|
|
||||||
// Force bindings to apply
|
|
||||||
settings[0].clientTop;
|
|
||||||
|
|
||||||
ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
|
ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
|
||||||
Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false);
|
Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false);
|
||||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input");
|
var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input");
|
||||||
@ -288,9 +303,6 @@ add_test(function() {
|
|||||||
var settings = grid.querySelectorAll("rows > setting");
|
var settings = grid.querySelectorAll("rows > setting");
|
||||||
is(settings.length, 4, "Grid should have settings children");
|
is(settings.length, 4, "Grid should have settings children");
|
||||||
|
|
||||||
// Force bindings to apply
|
|
||||||
settings[0].clientTop;
|
|
||||||
|
|
||||||
ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
|
ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
|
||||||
Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false);
|
Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false);
|
||||||
var radios = settings[0].getElementsByTagName("radio");
|
var radios = settings[0].getElementsByTagName("radio");
|
||||||
@ -354,9 +366,6 @@ add_test(function() {
|
|||||||
var settings = grid.querySelectorAll("rows > setting");
|
var settings = grid.querySelectorAll("rows > setting");
|
||||||
is(settings.length, 5, "Grid should have settings children");
|
is(settings.length, 5, "Grid should have settings children");
|
||||||
|
|
||||||
// Force bindings to apply
|
|
||||||
settings[0].clientTop;
|
|
||||||
|
|
||||||
var node = settings[0];
|
var node = settings[0];
|
||||||
node = settings[0];
|
node = settings[0];
|
||||||
is_element_hidden(node, "Unsupported settings should not be visible");
|
is_element_hidden(node, "Unsupported settings should not be visible");
|
||||||
@ -439,10 +448,15 @@ add_test(function() {
|
|||||||
var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org");
|
var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org");
|
||||||
addon.parentNode.ensureElementIsVisible(addon);
|
addon.parentNode.ensureElementIsVisible(addon);
|
||||||
|
|
||||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
|
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||||
|
|
||||||
wait_for_view_load(gManagerWindow, function() {
|
wait_for_view_load(gManagerWindow, function() {
|
||||||
|
is(gManagerWindow.gViewController.currentViewId,
|
||||||
|
"addons://detail/inlinesettings1%40tests.mozilla.org",
|
||||||
|
"Current view should not scroll to preferences");
|
||||||
|
checkScrolling(false);
|
||||||
|
|
||||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||||
var settings = grid.querySelectorAll("rows > setting");
|
var settings = grid.querySelectorAll("rows > setting");
|
||||||
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
min-height: 41px;
|
min-height: 41px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.global-warning-text {
|
.global-warning-text {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Maximize the size of the viewport when the window is small */
|
/* Maximize the size of the viewport when the window is small */
|
||||||
@media all and (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
.category-name {
|
.category-name {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
border-bottom: 1px solid rgba(50, 65, 92, 0.4);
|
border-bottom: 1px solid rgba(50, 65, 92, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.global-warning-text {
|
.global-warning-text {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Maximize the size of the viewport when the window is small */
|
/* Maximize the size of the viewport when the window is small */
|
||||||
@media all and (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
.category-name {
|
.category-name {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ html|html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
%ifdef WINSTRIPE_AERO
|
%ifdef WINSTRIPE_AERO
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
*|*:root {
|
*|*:root {
|
||||||
color: #000;
|
color: #000;
|
||||||
background-color: #CCD9EA;
|
background-color: #CCD9EA;
|
||||||
@ -72,7 +72,7 @@ html|html {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-compositor) {
|
@media (-moz-windows-compositor) {
|
||||||
*|*:root {
|
*|*:root {
|
||||||
color: #000;
|
color: #000;
|
||||||
/* Blame shorlander for this monstrosity. */
|
/* Blame shorlander for this monstrosity. */
|
||||||
@ -117,7 +117,7 @@ html|html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
%ifdef WINSTRIPE_AERO
|
%ifdef WINSTRIPE_AERO
|
||||||
@media all and (-moz-windows-compositor) {
|
@media (-moz-windows-compositor) {
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
*|button,
|
*|button,
|
||||||
menulist,
|
menulist,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
%include menu.css
|
%include menu.css
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
menubar > menu:-moz-lwtheme {
|
menubar > menu:-moz-lwtheme {
|
||||||
-moz-appearance: menuitem;
|
-moz-appearance: menuitem;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ menuitem[_moz-menuactive="true"][disabled="true"],
|
|||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-classic) {
|
@media (-moz-windows-classic) {
|
||||||
menu[disabled="true"],
|
menu[disabled="true"],
|
||||||
menubar > menu[disabled="true"][_moz-menuactive="true"],
|
menubar > menu[disabled="true"][_moz-menuactive="true"],
|
||||||
menuitem[disabled="true"],
|
menuitem[disabled="true"],
|
||||||
|
@ -70,7 +70,7 @@ notification[type="critical"] .messageImage {
|
|||||||
%ifdef XP_WIN
|
%ifdef XP_WIN
|
||||||
/*
|
/*
|
||||||
XXX: apply styles to all themes until bug 509642 is fixed
|
XXX: apply styles to all themes until bug 509642 is fixed
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
*/
|
*/
|
||||||
.popup-notification-menubutton[type="menu-button"] {
|
.popup-notification-menubutton[type="menu-button"] {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
@ -131,7 +131,7 @@ panel[type="arrow"] {
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%ifdef XP_WIN
|
%ifdef XP_WIN
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
panel[type="arrow"][side="top"],
|
panel[type="arrow"][side="top"],
|
||||||
panel[type="arrow"][side="bottom"] {
|
panel[type="arrow"][side="bottom"] {
|
||||||
margin-left: -25px;
|
margin-left: -25px;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
%include toolbarbutton.css
|
%include toolbarbutton.css
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
toolbarbutton:-moz-lwtheme:not([disabled="true"]) {
|
toolbarbutton:-moz-lwtheme:not([disabled="true"]) {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-shadow: inherit;
|
text-shadow: inherit;
|
||||||
|
@ -96,7 +96,7 @@ toolbarbutton[disabled="true"] {
|
|||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-classic) {
|
@media (-moz-windows-classic) {
|
||||||
toolbarbutton[disabled="true"] {
|
toolbarbutton[disabled="true"] {
|
||||||
color: ThreeDShadow;
|
color: ThreeDShadow;
|
||||||
text-shadow: 1px 1px ThreeDHighlight;
|
text-shadow: 1px 1px ThreeDHighlight;
|
||||||
@ -113,7 +113,7 @@ toolbarbutton[checked="true"]:not([disabled="true"]) {
|
|||||||
color: ButtonText;
|
color: ButtonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
toolbarbutton:-moz-lwtheme {
|
toolbarbutton:-moz-lwtheme {
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
%include downloads.css
|
%include downloads.css
|
||||||
|
|
||||||
@media all and (-moz-windows-compositor) {
|
@media (-moz-windows-compositor) {
|
||||||
#downloadManager {
|
#downloadManager {
|
||||||
-moz-appearance: -moz-win-glass;
|
-moz-appearance: -moz-win-glass;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
color: -moz-DialogText;
|
color: -moz-DialogText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-compositor) {
|
@media (-moz-windows-compositor) {
|
||||||
#genericAbout {
|
#genericAbout {
|
||||||
-moz-appearance: -moz-win-glass;
|
-moz-appearance: -moz-win-glass;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
border-bottom: 1px solid #CAD4E0;
|
border-bottom: 1px solid #CAD4E0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.global-warning-text {
|
.global-warning-text {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Maximize the size of the viewport when the window is small */
|
/* Maximize the size of the viewport when the window is small */
|
||||||
@media all and (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
.category-name {
|
.category-name {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#header-search {
|
#header-search {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.32);
|
border: 1px solid rgba(0, 0, 0, 0.32);
|
||||||
|
@ -207,7 +207,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
%ifdef WINSTRIPE_AERO
|
%ifdef WINSTRIPE_AERO
|
||||||
@media all and (-moz-windows-default-theme) {
|
@media (-moz-windows-default-theme) {
|
||||||
#footer {
|
#footer {
|
||||||
background-color: #f1f5fb;
|
background-color: #f1f5fb;
|
||||||
box-shadow: 0px 1px 2px rgb(204,214,234) inset;
|
box-shadow: 0px 1px 2px rgb(204,214,234) inset;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* vim:set ts=4 sw=4 sts=4 et cindent: */
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
*
|
*
|
||||||
@ -59,9 +59,14 @@ public:
|
|||||||
|
|
||||||
SharedLibrary& operator=(const SharedLibrary& aEntry)
|
SharedLibrary& operator=(const SharedLibrary& aEntry)
|
||||||
{
|
{
|
||||||
|
// Gracefully handle self assignment
|
||||||
|
if (this == &aEntry) return *this;
|
||||||
|
|
||||||
mStart = aEntry.mStart;
|
mStart = aEntry.mStart;
|
||||||
mEnd = aEntry.mEnd;
|
mEnd = aEntry.mEnd;
|
||||||
mOffset = aEntry.mOffset;
|
mOffset = aEntry.mOffset;
|
||||||
|
if (mName)
|
||||||
|
free(mName);
|
||||||
mName = strdup(aEntry.mName);
|
mName = strdup(aEntry.mName);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -408,6 +408,10 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
|
|||||||
mType = jenv->GetIntField(jobj, jTypeField);
|
mType = jenv->GetIntField(jobj, jTypeField);
|
||||||
|
|
||||||
switch (mType) {
|
switch (mType) {
|
||||||
|
case TILE_SIZE:
|
||||||
|
ReadP0Field(jenv);
|
||||||
|
break;
|
||||||
|
|
||||||
case SIZE_CHANGED:
|
case SIZE_CHANGED:
|
||||||
ReadP0Field(jenv);
|
ReadP0Field(jenv);
|
||||||
ReadP1Field(jenv);
|
ReadP1Field(jenv);
|
||||||
|
@ -532,6 +532,7 @@ public:
|
|||||||
ACTIVITY_START = 17,
|
ACTIVITY_START = 17,
|
||||||
BROADCAST = 19,
|
BROADCAST = 19,
|
||||||
VIEWPORT = 20,
|
VIEWPORT = 20,
|
||||||
|
TILE_SIZE = 21,
|
||||||
dummy_java_enum_list_end
|
dummy_java_enum_list_end
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
|
|||||||
|
|
||||||
// The dimensions of the current android view
|
// The dimensions of the current android view
|
||||||
static gfxIntSize gAndroidBounds = gfxIntSize(0, 0);
|
static gfxIntSize gAndroidBounds = gfxIntSize(0, 0);
|
||||||
|
static gfxIntSize gAndroidTileSize = gfxIntSize(0, 0);
|
||||||
static gfxIntSize gAndroidScreenBounds;
|
static gfxIntSize gAndroidScreenBounds;
|
||||||
|
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
@ -981,6 +982,12 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
|
|||||||
win->OnDraw(ae);
|
win->OnDraw(ae);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AndroidGeckoEvent::TILE_SIZE: {
|
||||||
|
gAndroidTileSize.width = ae->P0().x;
|
||||||
|
gAndroidTileSize.height = ae->P0().y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AndroidGeckoEvent::IME_EVENT:
|
case AndroidGeckoEvent::IME_EVENT:
|
||||||
win->UserActivity();
|
win->UserActivity();
|
||||||
if (win->mFocus) {
|
if (win->mFocus) {
|
||||||
@ -1196,42 +1203,56 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
|||||||
sDirectTexture->Reallocate(gAndroidBounds.width, gAndroidBounds.height);
|
sDirectTexture->Reallocate(gAndroidBounds.width, gAndroidBounds.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
sDirectTexture->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, &bits);
|
sDirectTexture->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, ae->Rect(), &bits);
|
||||||
} else {
|
} else {
|
||||||
bits = client.LockBufferBits();
|
bits = client.LockBufferBits();
|
||||||
}
|
}
|
||||||
if (!bits) {
|
if (!bits) {
|
||||||
ALOG("### Failed to lock buffer");
|
ALOG("### Failed to lock buffer");
|
||||||
|
|
||||||
if (sHasDirectTexture) {
|
|
||||||
sDirectTexture->Unlock();
|
|
||||||
} else {
|
|
||||||
client.UnlockBuffer();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
nsRefPtr<gfxImageSurface> targetSurface =
|
// If tile size is 0,0, we assume we only have a single tile
|
||||||
new gfxImageSurface(bits, gfxIntSize(gAndroidBounds.width, gAndroidBounds.height), gAndroidBounds.width * 2,
|
int tileWidth = (gAndroidTileSize.width > 0) ? gAndroidTileSize.width : gAndroidBounds.width;
|
||||||
gfxASurface::ImageFormatRGB16_565);
|
int tileHeight = (gAndroidTileSize.height > 0) ? gAndroidTileSize.height : gAndroidBounds.height;
|
||||||
if (targetSurface->CairoStatus()) {
|
|
||||||
ALOG("### Failed to create a valid surface from the bitmap");
|
|
||||||
} else {
|
|
||||||
if (sHasDirectTexture) {
|
|
||||||
// XXX: lock only the dirty rect above and pass it in here
|
|
||||||
DrawTo(targetSurface);
|
|
||||||
} else {
|
|
||||||
DrawTo(targetSurface, ae->Rect());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (metadataProvider) {
|
bool drawSuccess = true;
|
||||||
metadataProvider->GetDrawMetadata(metadata);
|
int offset = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y < gAndroidBounds.height; y += tileHeight) {
|
||||||
|
for (int x = 0; x < gAndroidBounds.width; x += tileWidth) {
|
||||||
|
int width = NS_MIN(tileWidth, gAndroidBounds.width - x);
|
||||||
|
int height = NS_MIN(tileHeight, gAndroidBounds.height - y);
|
||||||
|
|
||||||
|
nsRefPtr<gfxImageSurface> targetSurface =
|
||||||
|
new gfxImageSurface(bits + offset,
|
||||||
|
gfxIntSize(width, height),
|
||||||
|
width * 2,
|
||||||
|
gfxASurface::ImageFormatRGB16_565);
|
||||||
|
|
||||||
|
offset += width * height * 2;
|
||||||
|
|
||||||
|
if (targetSurface->CairoStatus()) {
|
||||||
|
ALOG("### Failed to create a valid surface from the bitmap");
|
||||||
|
drawSuccess = false;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
targetSurface->SetDeviceOffset(gfxPoint(-x, -y));
|
||||||
|
DrawTo(targetSurface, ae->Rect());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sHasDirectTexture) {
|
|
||||||
sDirectTexture->Unlock();
|
// Don't fill in the draw metadata on an unsuccessful draw
|
||||||
} else {
|
if (drawSuccess && metadataProvider) {
|
||||||
client.UnlockBuffer();
|
metadataProvider->GetDrawMetadata(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sHasDirectTexture) {
|
||||||
|
sDirectTexture->Unlock();
|
||||||
|
} else {
|
||||||
|
client.UnlockBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
client.EndDrawing(ae->Rect(), metadata);
|
client.EndDrawing(ae->Rect(), metadata);
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
@ -191,12 +191,25 @@ nsWindow::Show(bool aState)
|
|||||||
if (mWindowType == eWindowType_invisible)
|
if (mWindowType == eWindowType_invisible)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
if (mVisible == aState)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
mVisible = aState;
|
mVisible = aState;
|
||||||
if (!IS_TOPLEVEL())
|
if (!IS_TOPLEVEL())
|
||||||
return mParent ? mParent->Show(aState) : NS_OK;
|
return mParent ? mParent->Show(aState) : NS_OK;
|
||||||
|
|
||||||
if (aState)
|
if (aState) {
|
||||||
BringToTop();
|
BringToTop();
|
||||||
|
} else {
|
||||||
|
for (unsigned int i = 0; i < sTopWindows.Length(); i++) {
|
||||||
|
nsWindow *win = sTopWindows[i];
|
||||||
|
if (!win->mVisible)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
win->BringToTop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -210,8 +223,8 @@ nsWindow::IsVisible(bool & aState)
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsWindow::ConstrainPosition(bool aAllowSlop,
|
nsWindow::ConstrainPosition(bool aAllowSlop,
|
||||||
PRInt32 *aX,
|
PRInt32 *aX,
|
||||||
PRInt32 *aY)
|
PRInt32 *aY)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -287,10 +300,8 @@ nsWindow::Invalidate(const nsIntRect &aRect,
|
|||||||
nsWindow *parent = mParent;
|
nsWindow *parent = mParent;
|
||||||
while (parent && parent != sTopWindows[0])
|
while (parent && parent != sTopWindows[0])
|
||||||
parent = parent->mParent;
|
parent = parent->mParent;
|
||||||
if (parent != sTopWindows[0]) {
|
if (parent != sTopWindows[0])
|
||||||
LOG(" parent isn't top window, bailing");
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
|
||||||
|
|
||||||
mDirtyRegion.Or(mDirtyRegion, aRect);
|
mDirtyRegion.Or(mDirtyRegion, aRect);
|
||||||
gWindowToRedraw = this;
|
gWindowToRedraw = this;
|
||||||
@ -350,13 +361,13 @@ NS_IMETHODIMP_(void)
|
|||||||
nsWindow::SetInputContext(const InputContext& aContext,
|
nsWindow::SetInputContext(const InputContext& aContext,
|
||||||
const InputContextAction& aAction)
|
const InputContextAction& aAction)
|
||||||
{
|
{
|
||||||
mInputContext = aContext;
|
mInputContext = aContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(InputContext)
|
NS_IMETHODIMP_(InputContext)
|
||||||
nsWindow::GetInputContext()
|
nsWindow::GetInputContext()
|
||||||
{
|
{
|
||||||
return mInputContext;
|
return mInputContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -429,5 +440,6 @@ nsWindow::BringToTop()
|
|||||||
|
|
||||||
nsGUIEvent event(true, NS_ACTIVATE, this);
|
nsGUIEvent event(true, NS_ACTIVATE, this);
|
||||||
(*mEventCallback)(&event);
|
(*mEventCallback)(&event);
|
||||||
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user