Merging cedar with mozilla-central.

This commit is contained in:
Mounir Lamouri 2011-06-01 10:06:55 +02:00
commit ba98c26241
53 changed files with 4805 additions and 4307 deletions

View File

@ -2032,7 +2032,7 @@ let GroupItems = {
if (UI.shouldLoadFavIcon(xulTab.linkedBrowser))
iconUrl = UI.getFavIconUrlForTab(xulTab);
else
iconUrl = Utils.defaultFaviconURL;
iconUrl = gFavIconService.defaultFavicon.spec;
return iconUrl;
},

View File

@ -490,8 +490,6 @@ Subscribable.prototype = {
// Class: Utils
// Singelton with common utility functions.
let Utils = {
defaultFaviconURL: "chrome://mozapps/skin/places/defaultFavicon.png",
// ----------
// Function: toString
// Prints [Utils] for debug use

View File

@ -47,8 +47,6 @@ let Storage = {
GROUPS_DATA_IDENTIFIER: "tabview-groups",
TAB_DATA_IDENTIFIER: "tabview-tab",
UI_DATA_IDENTIFIER: "tabview-ui",
CACHE_CLIENT_IDENTIFIER: "tabview-cache",
CACHE_PREFIX: "moz-panorama:",
// ----------
// Function: toString
@ -64,28 +62,12 @@ let Storage = {
this._sessionStore =
Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
// Create stream-based cache session for tabview
let cacheService =
Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
this._cacheSession = cacheService.createSession(
this.CACHE_CLIENT_IDENTIFIER, Ci.nsICache.STORE_ON_DISK, true);
this.StringInputStream = Components.Constructor(
"@mozilla.org/io/string-input-stream;1", "nsIStringInputStream",
"setData");
this.StorageStream = Components.Constructor(
"@mozilla.org/storagestream;1", "nsIStorageStream",
"init");
},
// ----------
// Function: uninit
uninit: function Storage_uninit () {
this._sessionStore = null;
this._cacheSession = null;
this.StringInputStream = null;
this.StorageStream = null;
},
// ----------
@ -114,137 +96,6 @@ let Storage = {
}
},
// ----------
// Function: _openCacheEntry
// Opens a cache entry for the given <url> and requests access <access>.
// Calls <successCallback>(entry) when the entry was successfully opened with
// requested access rights. Otherwise calls <errorCallback>().
_openCacheEntry: function Storage__openCacheEntry(url, access, successCallback, errorCallback) {
let onCacheEntryAvailable = function (entry, accessGranted, status) {
if (entry && access == accessGranted && Components.isSuccessCode(status)) {
successCallback(entry);
} else {
entry && entry.close();
errorCallback();
}
}
let key = this.CACHE_PREFIX + url;
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
let entry = this._cacheSession.openCacheEntry(key, access, true);
let status = Components.results.NS_OK;
onCacheEntryAvailable(entry, entry.accessGranted, status);
} else {
let listener = new CacheListener(onCacheEntryAvailable);
this._cacheSession.asyncOpenCacheEntry(key, access, listener);
}
},
// ----------
// Function: saveThumbnail
// Saves the <imageData> to the cache using the given <url> as key.
// Calls <callback>(status) when finished (passing true or false indicating
// whether the operation succeeded).
saveThumbnail: function Storage_saveThumbnail(url, imageData, callback) {
Utils.assert(url, "url");
Utils.assert(imageData, "imageData");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let self = this;
let StringInputStream = this.StringInputStream;
let onCacheEntryAvailable = function (entry) {
let outputStream = entry.openOutputStream(0);
let cleanup = function () {
outputStream.close();
entry.close();
}
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
outputStream.write(imageData, imageData.length);
cleanup();
callback(true);
return;
}
// asynchronous mode
let inputStream = new StringInputStream(imageData, imageData.length);
gNetUtil.asyncCopy(inputStream, outputStream, function (result) {
cleanup();
inputStream.close();
callback(Components.isSuccessCode(result));
});
}
let onCacheEntryUnavailable = function () {
callback(false);
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_WRITE,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: loadThumbnail
// Asynchrously loads image data from the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded) and the retrieved image data.
loadThumbnail: function Storage_loadThumbnail(url, callback) {
Utils.assert(url, "url");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let self = this;
let onCacheEntryAvailable = function (entry) {
let imageChunks = [];
let nativeInputStream = entry.openInputStream(0);
const CHUNK_SIZE = 0x10000; // 65k
const PR_UINT32_MAX = 0xFFFFFFFF;
let storageStream = new self.StorageStream(CHUNK_SIZE, PR_UINT32_MAX, null);
let storageOutStream = storageStream.getOutputStream(0);
let cleanup = function () {
nativeInputStream.close();
storageStream.close();
storageOutStream.close();
entry.close();
}
gNetUtil.asyncCopy(nativeInputStream, storageOutStream, function (result) {
// cancel if parent window has already been closed
if (typeof UI == "undefined") {
cleanup();
return;
}
let imageData = null;
let isSuccess = Components.isSuccessCode(result);
if (isSuccess) {
let storageInStream = storageStream.newInputStream(0);
imageData = gNetUtil.readInputStreamToString(storageInStream,
storageInStream.available());
storageInStream.close();
}
cleanup();
callback(isSuccess, imageData);
});
}
let onCacheEntryUnavailable = function () {
callback(false);
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_READ,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: saveTab
// Saves the data for a single tab.
@ -255,16 +106,9 @@ let Storage = {
let imageData = data.imageData;
// Remove imageData from payload
delete data.imageData;
if (imageData != null) {
this.saveThumbnail(data.url, imageData, function (status) {
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("savedCachedImageData");
} else {
Utils.log("Error while saving thumbnail: " + e);
}
});
}
if (imageData != null)
ThumbnailStorage.saveThumbnail(tab, imageData);
}
this._sessionStore.setTabValue(tab, this.TAB_DATA_IDENTIFIER,
@ -292,18 +136,13 @@ let Storage = {
}
if (existingData) {
this.loadThumbnail(existingData.url, function (status, imageData) {
if (status) {
ThumbnailStorage.loadThumbnail(
tab, existingData.url,
function(status, imageData) {
callback(imageData);
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("loadedCachedImageData");
} else {
Utils.log("Error while loading thumbnail");
}
});
);
}
return existingData;
},
@ -409,26 +248,3 @@ let Storage = {
}
};
// ##########
// Class: CacheListener
// Generic CacheListener for feeding to asynchronous cache calls.
// Calls <callback>(entry, access, status) when the requested cache entry
// is available.
function CacheListener(callback) {
Utils.assert(typeof callback == "function", "callback arg must be a function");
this.callback = callback;
};
CacheListener.prototype = {
// ----------
// Function: toString
// Prints [CacheListener] for debug use
toString: function CacheListener_toString() {
return "[CacheListener]";
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener]),
onCacheEntryAvailable: function (entry, access, status) {
this.callback(entry, access, status);
}
};

View File

@ -1,6 +1,7 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource:///modules/tabview/AllTabs.jsm");
Cu.import("resource:///modules/tabview/utils.jsm");
@ -50,5 +51,6 @@ var gTabViewFrame = gWindow.document.getElementById("tab-view");
#include tabitems.js
#include drag.js
#include trench.js
#include thumbnailStorage.js
#include ui.js
#include search.js

View File

@ -0,0 +1,373 @@
/* ***** 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 thumbnailStorage.js.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.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 ***** */
// **********
// Title: thumbnailStorage.js
// ##########
// Class: ThumbnailStorage
// Singleton for persistent storage of thumbnail data.
let ThumbnailStorage = {
CACHE_CLIENT_IDENTIFIER: "tabview-cache",
CACHE_PREFIX: "moz-panorama:",
PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
// Holds the cache session reference
_cacheSession: null,
// Holds the string input stream reference
_stringInputStream: null,
// Holds the storage stream reference
_storageStream: null,
// Holds the progress listener reference
_progressListener: null,
// Used to keep track of disk_cache_ssl preference
enablePersistentHttpsCaching: null,
// Used to keep track of browsers whose thumbs we shouldn't save
excludedBrowsers: [],
// ----------
// Function: toString
// Prints [ThumbnailStorage] for debug use.
toString: function ThumbnailStorage_toString() {
return "[ThumbnailStorage]";
},
// ----------
// Function: init
// Should be called when UI is initialized.
init: function ThumbnailStorage_init() {
// Create stream-based cache session for tabview
let cacheService =
Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
this._cacheSession = cacheService.createSession(
this.CACHE_CLIENT_IDENTIFIER, Ci.nsICache.STORE_ON_DISK, true);
this._stringInputStream = Components.Constructor(
"@mozilla.org/io/string-input-stream;1", "nsIStringInputStream",
"setData");
this._storageStream = Components.Constructor(
"@mozilla.org/storagestream;1", "nsIStorageStream",
"init");
// store the preference value
this.enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
let self = this;
// tabs are already loaded before UI is initialized so cache-control
// values are unknown. We add browsers with https to the list for now.
gBrowser.browsers.forEach(function(browser) {
let checkAndAddToList = function(browserObj) {
if (!self.enablePersistentHttpsCaching &&
browserObj.currentURI.schemeIs("https"))
self.excludedBrowsers.push(browserObj);
};
if (browser.contentDocument.readyState != "complete" ||
browser.webProgress.isLoadingDocument) {
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);
checkAndAddToList(browser);
}, true);
} else {
checkAndAddToList(browser);
}
});
gBrowser.addTabsProgressListener(this);
},
// Function: uninit
// Should be called when window is unloaded.
uninit: function ThumbnailStorage_uninit() {
gBrowser.removeTabsProgressListener(this);
Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
},
// ----------
// Function: _openCacheEntry
// Opens a cache entry for the given <url> and requests access <access>.
// Calls <successCallback>(entry) when the entry was successfully opened with
// requested access rights. Otherwise calls <errorCallback>().
_openCacheEntry: function ThumbnailStorage__openCacheEntry(url, access, successCallback, errorCallback) {
let onCacheEntryAvailable = function(entry, accessGranted, status) {
if (entry && access == accessGranted && Components.isSuccessCode(status)) {
successCallback(entry);
} else {
entry && entry.close();
errorCallback();
}
}
let key = this.CACHE_PREFIX + url;
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
let entry = this._cacheSession.openCacheEntry(key, access, true);
let status = Cr.NS_OK;
onCacheEntryAvailable(entry, entry.accessGranted, status);
} else {
let listener = new CacheListener(onCacheEntryAvailable);
this._cacheSession.asyncOpenCacheEntry(key, access, listener);
}
},
// Function: _shouldSaveThumbnail
// Checks whether to save tab's thumbnail or not.
_shouldSaveThumbnail : function ThumbnailStorage__shouldSaveThumbnail(tab) {
return (this.excludedBrowsers.indexOf(tab.linkedBrowser) == -1);
},
// ----------
// Function: saveThumbnail
// Saves the <imageData> to the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded).
saveThumbnail: function ThumbnailStorage_saveThumbnail(tab, imageData, callback) {
Utils.assert(tab, "tab");
Utils.assert(imageData, "imageData");
if (!this._shouldSaveThumbnail(tab)) {
tab._tabViewTabItem._sendToSubscribers("deniedToCacheImageData");
if (callback)
callback(false);
return;
}
let self = this;
let completed = function(status) {
if (callback)
callback(status);
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("savedCachedImageData");
} else {
Utils.log("Error while saving thumbnail: " + e);
}
};
let onCacheEntryAvailable = function(entry) {
let outputStream = entry.openOutputStream(0);
let cleanup = function() {
outputStream.close();
entry.close();
}
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
outputStream.write(imageData, imageData.length);
cleanup();
completed(true);
return;
}
// asynchronous mode
let inputStream = new self._stringInputStream(imageData, imageData.length);
gNetUtil.asyncCopy(inputStream, outputStream, function (result) {
cleanup();
inputStream.close();
completed(Components.isSuccessCode(result));
});
}
let onCacheEntryUnavailable = function() {
completed(false);
}
this._openCacheEntry(tab.linkedBrowser.currentURI.spec,
Ci.nsICache.ACCESS_WRITE, onCacheEntryAvailable,
onCacheEntryUnavailable);
},
// ----------
// Function: loadThumbnail
// Asynchrously loads image data from the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded) and the retrieved image data.
loadThumbnail: function ThumbnailStorage_loadThumbnail(tab, url, callback) {
Utils.assert(tab, "tab");
Utils.assert(url, "url");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let self = this;
let completed = function(status, imageData) {
callback(status, imageData);
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("loadedCachedImageData");
} else {
Utils.log("Error while loading thumbnail");
}
}
let onCacheEntryAvailable = function(entry) {
let imageChunks = [];
let nativeInputStream = entry.openInputStream(0);
const CHUNK_SIZE = 0x10000; // 65k
const PR_UINT32_MAX = 0xFFFFFFFF;
let storageStream = new self._storageStream(CHUNK_SIZE, PR_UINT32_MAX, null);
let storageOutStream = storageStream.getOutputStream(0);
let cleanup = function () {
nativeInputStream.close();
storageStream.close();
storageOutStream.close();
entry.close();
}
gNetUtil.asyncCopy(nativeInputStream, storageOutStream, function (result) {
// cancel if parent window has already been closed
if (typeof UI == "undefined") {
cleanup();
return;
}
let imageData = null;
let isSuccess = Components.isSuccessCode(result);
if (isSuccess) {
let storageInStream = storageStream.newInputStream(0);
imageData = gNetUtil.readInputStreamToString(storageInStream,
storageInStream.available());
storageInStream.close();
}
cleanup();
completed(isSuccess, imageData);
});
}
let onCacheEntryUnavailable = function() {
completed(false);
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_READ,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: observe
// Implements the observer interface.
observe: function ThumbnailStorage_observe(subject, topic, data) {
this.enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
},
// ----------
// Implements progress listener interface.
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
onStateChange: function ThumbnailStorage_onStateChange(
browser, webProgress, request, flag, status) {
if (flag & Ci.nsIWebProgressListener.STATE_START &&
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
// ensure the dom window is the top one
if (webProgress.DOMWindow.parent == webProgress.DOMWindow) {
let index = this.excludedBrowsers.indexOf(browser);
if (index != -1)
this.excludedBrowsers.splice(index, 1);
}
}
if (flag & Ci.nsIWebProgressListener.STATE_STOP &&
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
// ensure the dom window is the top one
if (webProgress.DOMWindow.parent == webProgress.DOMWindow &&
request && request instanceof Ci.nsIHttpChannel) {
request.QueryInterface(Ci.nsIHttpChannel);
let inhibitPersistentThumb = false;
if (request.isNoStoreResponse()) {
inhibitPersistentThumb = true;
} else if (!this.enablePersistentHttpsCaching &&
request.URI.schemeIs("https")) {
let cacheControlHeader;
try {
cacheControlHeader = request.getResponseHeader("Cache-Control");
} catch(e) {
// this error would occur when "Cache-Control" doesn't exist in
// the eaders
}
if (cacheControlHeader && !(/public/i).test(cacheControlHeader))
inhibitPersistentThumb = true;
}
if (inhibitPersistentThumb &&
this.excludedBrowsers.indexOf(browser) == -1)
this.excludedBrowsers.push(browser);
}
}
}
}
// ##########
// Class: CacheListener
// Generic CacheListener for feeding to asynchronous cache calls.
// Calls <callback>(entry, access, status) when the requested cache entry
// is available.
function CacheListener(callback) {
Utils.assert(typeof callback == "function", "callback arg must be a function");
this.callback = callback;
};
CacheListener.prototype = {
// ----------
// Function: toString
// Prints [CacheListener] for debug use
toString: function CacheListener_toString() {
return "[CacheListener]";
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener]),
onCacheEntryAvailable: function CacheListener_onCacheEntryAvailable(
entry, access, status) {
this.callback(entry, access, status);
}
};

View File

@ -157,6 +157,9 @@ let UI = {
// initialize the direction of the page
this._initPageDirection();
// ___ thumbnail storage
ThumbnailStorage.init();
// ___ storage
Storage.init();
let data = Storage.readUIData(gWindow);
@ -278,7 +281,7 @@ let UI = {
// initialized.
let event = document.createEvent("Events");
event.initEvent("tabviewframeinitialized", true, false);
dispatchEvent(event);
dispatchEvent(event);
} catch(e) {
Utils.log(e);
} finally {
@ -286,6 +289,8 @@ let UI = {
}
},
// Function: uninit
// Should be called when window is unloaded.
uninit: function UI_uninit() {
// call our cleanup functions
this._cleanupFunctions.forEach(function(func) {
@ -297,6 +302,7 @@ let UI = {
TabItems.uninit();
GroupItems.uninit();
Storage.uninit();
ThumbnailStorage.uninit();
this._removeTabActionHandlers();
this._currentTab = null;
@ -680,22 +686,22 @@ let UI = {
// don't reenter Panorama due to all of the session restore tab
// manipulation (which otherwise we might). When transitioning away from
// PB, we reenter Panorama if we had been there directly before PB.
function pbObserver(aSubject, aTopic, aData) {
if (aTopic == "private-browsing") {
function pbObserver(subject, topic, data) {
if (topic == "private-browsing") {
// We could probably do this in private-browsing-change-granted, but
// this seems like a nicer spot, right in the middle of the process.
if (aData == "enter") {
if (data == "enter") {
// If we are in Tab View, exit.
self._privateBrowsing.wasInTabView = self.isTabViewVisible();
if (self.isTabViewVisible())
self.goToTab(gBrowser.selectedTab);
}
} else if (aTopic == "private-browsing-change-granted") {
if (aData == "enter" || aData == "exit") {
self._privateBrowsing.transitionMode = aData;
} else if (topic == "private-browsing-change-granted") {
if (data == "enter" || data == "exit") {
self._privateBrowsing.transitionMode = data;
self.storageBusy();
}
} else if (aTopic == "private-browsing-transition-complete") {
} else if (topic == "private-browsing-transition-complete") {
// We use .transitionMode here, as aData is empty.
if (self._privateBrowsing.transitionMode == "exit" &&
self._privateBrowsing.wasInTabView)
@ -990,21 +996,28 @@ let UI = {
[
#ifdef XP_UNIX
"quitApplication",
#else
"redo",
#endif
#ifdef XP_MACOSX
"preferencesCmdMac", "minimizeWindow",
#endif
"newNavigator", "newNavigatorTab", "undo", "cut", "copy", "paste",
"selectAll", "find"
].forEach(function(key) {
].forEach(function(key) {
let element = gWindow.document.getElementById("key_" + key);
keys[key] = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0);
});
// for key combinations with shift key, the charCode of upper case letters
// are different to the lower case ones so need to handle them differently.
["closeWindow", "tabview", "undoCloseTab", "undoCloseWindow",
"privatebrowsing", "redo"].forEach(function(key) {
[
#ifdef XP_UNIX
"redo",
#endif
"closeWindow", "tabview", "undoCloseTab", "undoCloseWindow",
"privatebrowsing"
].forEach(function(key) {
let element = gWindow.document.getElementById("key_" + key);
keys[key] = element.getAttribute("key").toLocaleUpperCase().charCodeAt(0);
});
@ -1039,22 +1052,33 @@ let UI = {
let preventDefault = true;
if (evt.shiftKey) {
switch (evt.charCode) {
case self._browserKeys.privatebrowsing:
case self._browserKeys.undoCloseTab:
case self._browserKeys.undoCloseWindow:
case self._browserKeys.closeWindow:
case self._browserKeys.redo:
preventDefault = false;
break;
case self._browserKeys.tabview:
self.exit();
break;
#ifdef XP_UNIX
case self._browserKeys.redo:
#endif
case self._browserKeys.closeWindow:
case self._browserKeys.undoCloseTab:
case self._browserKeys.undoCloseWindow:
case self._browserKeys.privatebrowsing:
preventDefault = false;
break;
}
} else {
switch (evt.charCode) {
case self._browserKeys.find:
self.enableSearch();
break;
#ifdef XP_UNIX
case self._browserKeys.quitApplication:
#else
case self._browserKeys.redo:
#endif
#ifdef XP_MACOSX
case self._browserKeys.preferencesCmdMac:
case self._browserKeys.minimizeWindow:
#endif
case self._browserKeys.newNavigator:
case self._browserKeys.newNavigatorTab:
case self._browserKeys.undo:
@ -1064,17 +1088,6 @@ let UI = {
case self._browserKeys.selectAll:
preventDefault = false;
break;
#ifdef XP_UNIX
case self._browserKeys.quitApplication:
preventDefault = false;
break;
#endif
#ifdef XP_MACOSX
case self._browserKeys.preferencesCmdMac:
case self._browserKeys.minimizeWindow:
preventDefault = false;
break;
#endif
}
}
if (preventDefault) {

View File

@ -113,6 +113,7 @@ _BROWSER_FILES = \
browser_tabview_bug626368.js \
browser_tabview_bug626525.js \
browser_tabview_bug626791.js \
browser_tabview_bug627239.js \
browser_tabview_bug627288.js \
browser_tabview_bug627736.js \
browser_tabview_bug628061.js \

View File

@ -1,6 +1,9 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const fi = Cc["@mozilla.org/browser/favicon-service;1"].
getService(Ci.nsIFaviconService);
let newTab;
function test() {
@ -27,7 +30,7 @@ function onTabViewWindowLoaded() {
is($icon.data("xulTab"), newTab,
"The app tab icon has the right tab reference")
// check to see whether it's showing the default one or not.
is($icon.attr("src"), contentWindow.Utils.defaultFaviconURL,
is($icon.attr("src"), fi.defaultFavicon.spec,
"The icon is showing the default fav icon for blank tab");
let errorHandler = function(event) {
@ -37,7 +40,7 @@ function onTabViewWindowLoaded() {
// fired, a delay is used here to avoid the test code run before the browser
// code.
executeSoon(function() {
is($icon.attr("src"), contentWindow.Utils.defaultFaviconURL,
is($icon.attr("src"), fi.defaultFavicon.spec,
"The icon is showing the default fav icon");
// clean up

View File

@ -2,8 +2,9 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let url = "http://non.existant/url";
let url = "http://www.example.com/";
let cw;
let tab = gBrowser.tabs[0];
let finishTest = function () {
is(1, gBrowser.tabs.length, "there is one tab, only");
@ -14,7 +15,7 @@ function test() {
waitForExplicitFinish();
let testErroneousLoading = function () {
cw.Storage.loadThumbnail(url, function (status, data) {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, data) {
ok(!status, "thumbnail entry failed to load");
is(null, data, "no thumbnail data received");
next();
@ -25,11 +26,11 @@ function test() {
let saved = false;
let data = "thumbnail-data-asynchronous";
cw.Storage.saveThumbnail(url, data, function (status) {
cw.ThumbnailStorage.saveThumbnail(tab, data, function (status) {
ok(status, "thumbnail entry was saved");
ok(saved, "thumbnail was saved asynchronously");
cw.Storage.loadThumbnail(url, function (status, imageData) {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, imageData) {
ok(status, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
next();
@ -46,11 +47,11 @@ function test() {
cw.UI.isDOMWindowClosing = true;
registerCleanupFunction(function () cw.UI.isDOMWindowClosing = false);
cw.Storage.saveThumbnail(url, data, function (status) {
cw.ThumbnailStorage.saveThumbnail(tab, data, function (status) {
ok(status, "thumbnail entry was saved");
ok(!saved, "thumbnail was saved synchronously");
cw.Storage.loadThumbnail(url, function (status, imageData) {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, imageData) {
ok(status, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
@ -72,10 +73,13 @@ function test() {
hideTabView(finishTest);
}
showTabView(function () {
registerCleanupFunction(function () TabView.hide());
cw = TabView.getContentWindow();
tab.linkedBrowser.loadURI(url);
afterAllTabsLoaded(function() {
showTabView(function () {
registerCleanupFunction(function () TabView.hide());
cw = TabView.getContentWindow();
next();
next();
});
});
}

View File

@ -0,0 +1,156 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let contentWindow;
let enablePersistentHttpsCaching;
let newTab;
function test() {
waitForExplicitFinish();
newTab = gBrowser.addTab();
HttpRequestObserver.register();
registerCleanupFunction(function () {
HttpRequestObserver.unregister();
if (gBrowser.tabs[1])
gBrowser.removeTab(gBrowser.tabs[1]);
hideTabView(function () {});
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching =
enablePersistentHttpsCaching;
});
showTabView(function() {
contentWindow = TabView.getContentWindow();
test1();
});
}
function test1() {
// page with cache-control: no-store, should not save thumbnail
HttpRequestObserver.cacheControlValue = "no-store";
newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should not save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
test2();
});
tabItem.save(true);
HttpRequestObserver.cacheControlValue = null;
});
}
function test2() {
// page with cache-control: private, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
newTab.linkedBrowser.loadURI("http://www.example.com/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
test3();
});
tabItem.save(true);
});
}
function test3() {
// page with cache-control: private with https caching enabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
enablePersistentHttpsCaching =
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching;
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = true;
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/dummy_page.html");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
test4();
});
tabItem.save(true);
});
}
function test4() {
// page with cache-control: public with https caching disabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "public";
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = false;
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
test5();
});
tabItem.save(true);
});
}
function test5() {
// page with cache-control: private with https caching disabled, should not save thumbnail
HttpRequestObserver.cacheControlValue = "private";
newTab.linkedBrowser.loadURI("https://example.com/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should not the thumbnail for tab");
tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
hideTabView(function () {
gBrowser.removeTab(gBrowser.tabs[1]);
finish();
});
});
tabItem.save(true);
});
}
let HttpRequestObserver = {
cacheControlValue: null,
observe: function(subject, topic, data) {
if (topic == "http-on-examine-response" && this.cacheControlValue) {
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
httpChannel.setResponseHeader("Cache-Control", this.cacheControlValue, false);
}
},
register: function() {
Services.obs.addObserver(this, "http-on-examine-response", false);
},
unregister: function() {
Services.obs.removeObserver(this, "http-on-examine-response");
}
};

View File

@ -7,17 +7,18 @@ var prefsBranch = Cc["@mozilla.org/preferences-service;1"].
function animateZoom() prefsBranch.getBoolPref("animate_zoom");
function registerCleanupFunction() {
prefsBranch.setUserPref("animate_zoom", true);
}
function test() {
waitForExplicitFinish();
let charsetArg = "charset=" + window.content.document.characterSet;
let win = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no",
"about:blank", charsetArg, null, null, true);
registerCleanupFunction(function() {
prefsBranch.setBoolPref("animate_zoom", true);
win.close();
});
ok(animateZoom(), "By default, we animate on zoom.");
prefsBranch.setBoolPref("animate_zoom", false);
ok(!animateZoom(), "animate_zoom = false");
@ -29,27 +30,24 @@ function test() {
let tabViewWindow = null;
let transitioned = 0;
let onShown = function() {
win.removeEventListener("tabviewshown", onShown, false);
ok(!transitioned, "There should be no transitions");
win.close();
finish();
};
let initCallback = function() {
tabViewWindow = win.TabView._window;
function onTransitionEnd(event) {
transitioned++;
tabViewWindow.Utils.log(transitioned);
info(transitioned);
}
tabViewWindow.document.addEventListener("transitionend", onTransitionEnd, false);
win.TabView.show();
showTabView(function() {
ok(!transitioned, "There should be no transitions");
tabViewWindow.document.removeEventListener(
"transitionend", onTransitionEnd, false);
finish();
}, win);
};
win.addEventListener("tabviewshown", onShown, false);
win.TabView._initFrame(initCallback);
}
win.addEventListener("load", onLoad, false);

View File

@ -31,7 +31,9 @@ function onTabViewWindowLoaded() {
is(groupItem.getChildren().length, 1, "The new group has a tab item");
// start the tests
testUndoGroup(contentWindow, groupItem);
waitForFocus(function() {
testUndoGroup(contentWindow, groupItem);
}, contentWindow);
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
window.addEventListener("tabviewshown", onTabViewShown, false);
@ -80,7 +82,7 @@ function testUndoGroup(contentWindow, groupItem) {
});
let closeButton = groupItem.container.getElementsByClassName("close");
ok(closeButton, "Group item close button exists");
ok(closeButton[0], "Group item close button exists");
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
}
@ -129,6 +131,6 @@ function testCloseUndoGroup(contentWindow, groupItem) {
});
let closeButton = groupItem.container.getElementsByClassName("close");
ok(closeButton, "Group item close button exists");
ok(closeButton[0], "Group item close button exists");
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
}

View File

@ -42,9 +42,9 @@
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="site" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<content>
<xul:hbox class="site-container" align="center">
<xul:hbox class="site-container" align="center" flex="1">
<xul:image xbl:inherits="src=favicon" class="site-favicon"/>
<xul:label xbl:inherits="value,selected" class="site-domain" crop="end"/>
<xul:label xbl:inherits="value,selected" class="site-domain" crop="end" flex="1"/>
</xul:hbox>
</content>
</binding>

View File

@ -19,11 +19,10 @@
#sites-box {
padding: 10px;
width: 25em;
}
.site {
width: 250px;
overflow-x: hidden;
padding: 4px;
border-bottom: 1px solid ThreeDLightShadow;
}
@ -39,10 +38,6 @@
list-style-image: none;
}
.site-domain {
max-width: 200px; /* crop set in XBL will ellipsize the domain if it's too long */
}
/* permissions box */
#permissions-box {

View File

@ -21,11 +21,10 @@
#sites-box {
padding: 10px;
width: 25em;
}
.site {
width: 250px;
overflow-x: hidden;
padding: 4px;
border-bottom: 1px solid ThreeDLightShadow;
}
@ -41,10 +40,6 @@
list-style-image: none;
}
.site-domain {
max-width: 200px; /* crop set in XBL will ellipsize the domain if it's too long */
}
/* permissions box */
#permissions-box {

View File

@ -24,11 +24,10 @@
#sites-box {
padding: 10px;
width: 25em;
}
.site {
width: 250px;
overflow-x: hidden;
padding: 4px;
border-bottom: 1px solid ThreeDLightShadow;
}
@ -44,10 +43,6 @@
list-style-image: none;
}
.site-domain {
max-width: 200px; /* crop set in XBL will ellipsize the domain if it's too long */
}
/* permissions box */
#permissions-box {

View File

@ -1326,6 +1326,31 @@ nsHTMLInputElement::SetFiles(const nsCOMArray<nsIDOMFile>& aFiles,
mFiles.Clear();
mFiles.AppendObjects(aFiles);
AfterSetFiles(aSetValueChanged);
}
void
nsHTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
bool aSetValueChanged)
{
mFiles.Clear();
if (aFiles) {
PRUint32 listLength;
aFiles->GetLength(&listLength);
for (PRUint32 i = 0; i < listLength; i++) {
nsCOMPtr<nsIDOMFile> file;
aFiles->Item(i, getter_AddRefs(file));
mFiles.AppendObject(file);
}
}
AfterSetFiles(aSetValueChanged);
}
void
nsHTMLInputElement::AfterSetFiles(bool aSetValueChanged)
{
// No need to flush here, if there's no frame at this point we
// don't need to force creation of one just to tell it about this
// new value. We just want the display to update as needed.

View File

@ -145,11 +145,11 @@ public:
{
return nsGenericHTMLElement::GetEditor(aEditor);
}
// Forward nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_NOFOCUSCLICK(nsGenericHTMLFormElement::)
NS_IMETHOD Focus();
NS_IMETHOD Click();
// Forward nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_NOFOCUSCLICK(nsGenericHTMLFormElement::)
NS_IMETHOD Focus();
NS_IMETHOD Click();
NS_IMETHOD SetUserInput(const nsAString& aInput);
@ -218,6 +218,7 @@ public:
void GetDisplayFileName(nsAString& aFileName) const;
const nsCOMArray<nsIDOMFile>& GetFiles() const;
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles, bool aSetValueChanged);
void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
void SetCheckedChangedInternal(PRBool aCheckedChanged);
PRBool GetCheckedChanged() const {
@ -457,6 +458,11 @@ protected:
*/
nsresult UpdateFileList();
/**
* Called after calling one of the SetFiles() functions.
*/
void AfterSetFiles(bool aSetValueChanged);
/**
* Determine whether the editor needs to be initialized explicitly for
* a particular event.

View File

@ -79,6 +79,7 @@ EXPORTS = \
nsPluginTags.h \
nsPluginDirServiceProvider.h \
nsPluginHost.h \
nsPluginInstanceOwner.h \
$(NULL)
EXPORTS_mozilla = \
@ -95,6 +96,7 @@ CPPSRCS = \
nsJSNPRuntime.cpp \
nsPluginTags.cpp \
PluginPRLibrary.cpp \
nsPluginInstanceOwner.cpp \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
@ -127,6 +129,7 @@ endif
LOCAL_INCLUDES = \
-I$(topsrcdir)/xpcom/base/ \
$(MOZ_CAIRO_CFLAGS) \
$(NULL)
ifneq (,$(filter WINNT Darwin,$(OS_ARCH)))
@ -146,6 +149,7 @@ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
EXTRA_DSO_LDOPTS += $(TK_LIBS)
endif
include $(topsrcdir)/dom/dom-config.mk
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,407 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* ***** 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 Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Jacek Piskozub <piskozub@iopan.gda.pl>
* Leon Sha <leon.sha@sun.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* Christian Biesinger <cbiesinger@web.de>
* Josh Aas <josh@mozilla.com>
* Mats Palmgren <matspal@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#ifndef nsPluginInstanceOwner_h_
#define nsPluginInstanceOwner_h_
#include "prtypes.h"
#include "npapi.h"
#include "nsCOMPtr.h"
#include "nsIPluginInstanceOwner.h"
#include "nsIPluginTagInfo.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMFocusListener.h"
#include "nsIScrollPositionListener.h"
#include "nsPluginHost.h"
#include "nsPluginNativeWindow.h"
#include "gfxRect.h"
#ifdef XP_MACOSX
#include "nsCoreAnimationSupport.h"
#include <ApplicationServices/ApplicationServices.h>
#endif
class nsIInputStream;
class nsIntRect;
class nsPluginDOMContextMenuListener;
class nsObjectFrame;
class nsDisplayListBuilder;
#ifdef MOZ_X11
class gfxXlibSurface;
#endif
#ifdef MOZ_WIDGET_GTK2
#include "gfxXlibNativeRenderer.h"
#endif
#ifdef MOZ_WIDGET_QT
#include "gfxQtNativeRenderer.h"
#endif
class nsPluginInstanceOwner : public nsIPluginInstanceOwner,
public nsIPluginTagInfo,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener,
public nsIDOMKeyListener,
public nsIDOMFocusListener,
public nsIScrollPositionListener
{
public:
nsPluginInstanceOwner();
virtual ~nsPluginInstanceOwner();
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGININSTANCEOWNER
NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
nsIInputStream *aPostStream,
void *aHeadersData, PRUint32 aHeadersDataLen);
NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
NPError ShowNativeContextMenu(NPMenu* menu, void* event);
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);
//nsIPluginTagInfo interface
NS_DECL_NSIPLUGINTAGINFO
// nsIDOMMouseListener interfaces
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// nsIDOMMouseMotionListener interfaces
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; }
// nsIDOMKeyListener interfaces
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
// nsIDOMFocusListener interfaces
NS_IMETHOD Focus(nsIDOMEvent * aFocusEvent);
NS_IMETHOD Blur(nsIDOMEvent * aFocusEvent);
nsresult Destroy();
void PrepareToStop(PRBool aDelayedStop);
#ifdef XP_WIN
void Paint(const RECT& aDirty, HDC aDC);
#elif defined(XP_MACOSX)
void Paint(const gfxRect& aDirtyRect, CGContextRef cgContext);
void RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight);
void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext);
#elif defined(MOZ_X11)
void Paint(gfxContext* aContext,
const gfxRect& aFrameRect,
const gfxRect& aDirtyRect);
#elif defined(XP_OS2)
void Paint(const nsRect& aDirtyRect, HPS aHPS);
#endif
#ifdef MAC_CARBON_PLUGINS
void CancelTimer();
void StartTimer(PRBool isVisible);
#endif
void SendIdleEvent();
// nsIScrollPositionListener interface
virtual void ScrollPositionWillChange(nscoord aX, nscoord aY);
virtual void ScrollPositionDidChange(nscoord aX, nscoord aY);
//locals
nsresult Init(nsPresContext* aPresContext, nsObjectFrame* aFrame,
nsIContent* aContent);
void* GetPluginPortFromWidget();
void ReleasePluginPort(void* pluginPort);
void SetPluginHost(nsIPluginHost* aHost);
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
#ifdef XP_MACOSX
enum { ePluginPaintEnable, ePluginPaintDisable };
NPDrawingModel GetDrawingModel();
PRBool IsRemoteDrawingCoreAnimation();
NPEventModel GetEventModel();
static void CARefresh(nsITimer *aTimer, void *aClosure);
static void AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
void SetupCARefresh();
void* FixUpPluginWindow(PRInt32 inPaintState);
void HidePluginWindow();
// Set a flag that (if true) indicates the plugin port info has changed and
// SetWindow() needs to be called.
void SetPluginPortChanged(PRBool aState) { mPluginPortChanged = aState; }
// Return a pointer to the internal nsPluginPort structure that's used to
// store a copy of plugin port info and to detect when it's been changed.
void* GetPluginPortCopy();
// Set plugin port info in the plugin (in the 'window' member of the
// NPWindow structure passed to the plugin by SetWindow()) and set a
// flag (mPluginPortChanged) to indicate whether or not this info has
// changed, and SetWindow() needs to be called again.
void* SetPluginPortAndDetectChange();
// Flag when we've set up a Thebes (and CoreGraphics) context in
// nsObjectFrame::PaintPlugin(). We need to know this in
// FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
// been called from nsObjectFrame::PaintPlugin() when we're using the
// CoreGraphics drawing model).
void BeginCGPaint();
void EndCGPaint();
#else // XP_MACOSX
void UpdateWindowPositionAndClipRect(PRBool aSetWindow);
void CallSetWindow();
void UpdateWindowVisibility(PRBool aVisible);
#endif // XP_MACOSX
void SetOwner(nsObjectFrame *aOwner)
{
mObjectFrame = aOwner;
}
nsObjectFrame* GetOwner() {
return mObjectFrame;
}
PRUint32 GetLastEventloopNestingLevel() const {
return mLastEventloopNestingLevel;
}
static PRUint32 GetEventloopNestingLevel();
void ConsiderNewEventloopNestingLevel() {
PRUint32 currentLevel = GetEventloopNestingLevel();
if (currentLevel < mLastEventloopNestingLevel) {
mLastEventloopNestingLevel = currentLevel;
}
}
const char* GetPluginName()
{
if (mInstance && mPluginHost) {
const char* name = NULL;
if (NS_SUCCEEDED(mPluginHost->GetPluginName(mInstance, &name)) && name)
return name;
}
return "";
}
#ifdef MOZ_X11
void GetPluginDescription(nsACString& aDescription)
{
aDescription.Truncate();
if (mInstance && mPluginHost) {
nsCOMPtr<nsIPluginTag> pluginTag;
mPluginHost->GetPluginTagForInstance(mInstance,
getter_AddRefs(pluginTag));
if (pluginTag) {
pluginTag->GetDescription(aDescription);
}
}
}
#endif
PRBool SendNativeEvents()
{
#ifdef XP_WIN
// XXX we should remove the plugin name check
return mPluginWindow->type == NPWindowTypeDrawable &&
(MatchPluginName("Shockwave Flash") ||
MatchPluginName("Test Plug-in"));
#elif defined(MOZ_X11) || defined(XP_MACOSX)
return PR_TRUE;
#else
return PR_FALSE;
#endif
}
PRBool MatchPluginName(const char *aPluginName)
{
return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0;
}
void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
// Return true if we set image with valid surface
PRBool SetCurrentImage(ImageContainer* aContainer);
/**
* Returns the bounds of the current async-rendered surface. This can only
* change in response to messages received by the event loop (i.e. not during
* painting).
*/
nsIntSize GetCurrentImageSize();
// Methods to update the background image we send to async plugins.
// The eventual target of these operations is PluginInstanceParent,
// but it takes several hops to get there.
void SetBackgroundUnknown();
already_AddRefed<gfxContext> BeginUpdateBackground(const nsIntRect& aRect);
void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect);
PRBool UseAsyncRendering()
{
PRBool useAsyncRendering;
return (mInstance &&
NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
useAsyncRendering &&
(!mPluginWindow ||
mPluginWindow->type == NPWindowTypeDrawable));
}
private:
// return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
PRBool IsUpToDate()
{
nsIntSize size;
return NS_SUCCEEDED(mInstance->GetImageSize(&size)) &&
size == nsIntSize(mPluginWindow->width, mPluginWindow->height);
}
void FixUpURLS(const nsString &name, nsAString &value);
nsPluginNativeWindow *mPluginWindow;
nsRefPtr<nsNPAPIPluginInstance> mInstance;
nsObjectFrame *mObjectFrame; // owns nsPluginInstanceOwner
nsCOMPtr<nsIContent> mContent;
nsCString mDocumentBase;
char *mTagText;
nsCOMPtr<nsIWidget> mWidget;
nsRefPtr<nsPluginHost> mPluginHost;
#ifdef XP_MACOSX
NP_CGContext mCGPluginPortCopy;
#ifndef NP_NO_QUICKDRAW
NP_Port mQDPluginPortCopy;
#endif
PRInt32 mInCGPaintLevel;
nsIOSurface *mIOSurface;
nsCARenderer mCARenderer;
CGColorSpaceRef mColorProfile;
static nsCOMPtr<nsITimer> *sCATimer;
static nsTArray<nsPluginInstanceOwner*> *sCARefreshListeners;
PRBool mSentInitialTopLevelWindowEvent;
#endif
// Initially, the event loop nesting level we were created on, it's updated
// if we detect the appshell is on a lower level as long as we're not stopped.
// We delay DoStopPlugin() until the appshell reaches this level or lower.
PRUint32 mLastEventloopNestingLevel;
PRPackedBool mContentFocused;
PRPackedBool mWidgetVisible; // used on Mac to store our widget's visible state
#ifdef XP_MACOSX
PRPackedBool mPluginPortChanged;
#endif
#ifdef MOZ_X11
// Used with windowless plugins only, initialized in CreateWidget().
PRPackedBool mFlash10Quirks;
#endif
PRPackedBool mPluginWindowVisible;
// If true, destroy the widget on destruction. Used when plugin stop
// is being delayed to a safer point in time.
PRPackedBool mDestroyWidget;
PRUint16 mNumCachedAttrs;
PRUint16 mNumCachedParams;
char **mCachedAttrParamNames;
char **mCachedAttrParamValues;
#ifdef XP_MACOSX
NPEventModel mEventModel;
#endif
// pointer to wrapper for nsIDOMContextMenuListener
nsRefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
nsresult EnsureCachedAttrParamArrays();
#ifdef MOZ_X11
class Renderer
#if defined(MOZ_WIDGET_GTK2)
: public gfxXlibNativeRenderer
#elif defined(MOZ_WIDGET_QT)
: public gfxQtNativeRenderer
#endif
{
public:
Renderer(NPWindow* aWindow, nsPluginInstanceOwner* aInstanceOwner,
const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
: mWindow(aWindow), mInstanceOwner(aInstanceOwner),
mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
{}
virtual nsresult DrawWithXlib(gfxXlibSurface* surface, nsIntPoint offset,
nsIntRect* clipRects, PRUint32 numClipRects);
private:
NPWindow* mWindow;
nsPluginInstanceOwner* mInstanceOwner;
const nsIntSize& mPluginSize;
const nsIntRect& mDirtyRect;
};
#endif
PRPackedBool mWaitingForPaint;
};
#endif // nsPluginInstanceOwner_h_

View File

@ -99,94 +99,6 @@
function(){new Effect.Highlight('nothing-to-see-here')});
}},
testCallbacks: function() { with(this) {
tmp = tmp2 = 0;
var e1 = new Effect.Opacity('sandbox',{from:1.0,to:0.5,duration:0.5,
beforeStart: function() { tmp++ },
beforeStartInternal: function() { tmp++ },
beforeSetup: function() { tmp++ },
beforeSetupInternal: function() { tmp++ },
afterSetup: function() { tmp++ },
afterSetupInternal: function() { tmp++ },
beforeUpdate: function() { tmp2++ },
beforeUpdateInternal: function() { tmp2++ },
beforeFinish: function() { tmp++ },
beforeFinishInternal: function() { tmp++ },
afterFinish: function() { tmp++ },
afterFinishInternal: function() { tmp++ }
});
wait(1000, function() {
assertEqual(10, tmp);
assert(tmp2 > 0);
});
}},
testEvent: function() { with(this) {
tmp = 0;
new Effect.Event({ afterFinish:function(){ tmp++ }, position:'end'});
wait(100, function() {
assertEqual(1, tmp);
});
}},
testTransition: function() { with(this) {
// false implies linear
var e = new Effect.Opacity('sandbox',{transition:false,from:0.0,to:0.25,duration:0.5});
assert(e.options.transition == Effect.Transitions.linear);
wait(1000, function() {
assertEqual(0.25, $('sandbox').getStyle('opacity'));
// default to sinoidal
var e = new Effect.Opacity('sandbox',{from:0.0,to:0.25,duration:0.5});
assert(e.options.transition == Effect.Transitions.sinoidal);
wait(1000, function() {
assertEqual(0.25, $('sandbox').getStyle('opacity'));
var transitions = [
{ transition: Effect.Transitions.linear, expected: 1 },
{ transition: Effect.Transitions.sinoidal, expected: 1 },
{ transition: Effect.Transitions.reverse, expected: 0 },
{ transition: Effect.Transitions.flicker, expected: 1 },
{ transition: Effect.Transitions.wobble, expected: 1 },
{ transition: Effect.Transitions.pulse, expected: 1 },
{ transition: Effect.Transitions.none, expected: 0 }
];
transitions.each(function(t){
var e = new Effect.Opacity('sandbox',{sync:true, from:0, to: 1, transition:t.transition});
assert(e.options.transition == t.transition);
e.render(1.0);
assertEqual(t.expected, e.position, t.transition);
});
});
});
}},
testInspect: function() { with(this) {
var e1 = new Effect.Opacity('sandbox',{from:1.0,to:0.5,duration:0.5});
info( e1.inspect() );
assertEqual(0, e1.inspect().indexOf('#<Effect:'));
assert(e1.inspect().indexOf('idle')>0);
wait(1000, function() {
assert(e1.inspect().indexOf('finished')>0);
});
}},
testDefaultOptions: function() { with(this) {
var oldDefaultOptions = Object.extend({},Effect.DefaultOptions);
assertEqual(1.0, Effect.DefaultOptions.duration);
Effect.DefaultOptions.duration = 0.5;
var e1 = new Effect.Opacity('sandbox');
assertEqual(0.5, e1.options.duration);
wait(750, function() {
assertEqual('finished', e1.state);
Effect.DefaultOptions = oldDefaultOptions;
});
}},
testEffectsQueue: function() { with(this) {
var e1 = new Effect.Highlight('sandbox');
var e2 = new Effect.Appear('sandbox');
@ -330,177 +242,6 @@
});
}},
testSynchronizedEffects: function() { with(this) {
var e1 = new Effect.Fade('sandbox',{sync:true});
wait(250, function() {
// effect should still be at frame 0
assertEqual(0, e1.currentFrame);
assertEqual('idle', e1.state);
e1.render(0.01);
// no frame count for sync effects
assertEqual(0, e1.currentFrame);
assertEqual('running', e1.state);
});
}},
testEffectPosition: function() { with(this) {
var testeffect = new Effect.Opacity('sandbox',{
afterSetup: function(effect) { effect.frames = 0; },
afterUpdate: function(effect) { effect.frames++; $('sandbox').update(effect.position); },
duration: 0.5, from: 1.0, to: 0.5
});
assertNull(testeffect.position);
assertEqual('idle', testeffect.state);
wait(1000, function() {
info('Rendered ' + testeffect.frames + ' frames in .5 seconds ' +
'(~' + (testeffect.frames/0.5) + 'fps of a possible 60fps, ' +
'note that this can exceed 60fps because of additional last frame rendering)');
assertEqual('0.5', $('sandbox').innerHTML);
assertEqual(0.5, testeffect.position);
assertEqual('finished', testeffect.state);
});
}},
testRenderPerformance: function() { with(this) {
info('The render() method is generated on a per-effect basis')
var e = new Effect.Opacity('sandbox',{sync:true});
benchmark(function(){
e.render(0.5);
},1000, 'Without events');
var e = new Effect.Opacity('sandbox',{sync:true,afterUpdate:function(){return}});
benchmark(function(){
e.render(0.5);
},1000, 'With afterUpdate event');
}},
testElementMorph: function() { with(this) {
$('error_test_ul').morph('font-size:40px', {duration: 0.5}).setStyle({marginRight:'17px'});
$('error_message_2').morph({
fontSize: '20px',
color: '#f00',
backgroundColor: '#ffffff'
},
{
duration:0.5
});
$('error_message_3').morph('final', {duration:0.5});
wait(2000,function(){
assertEqual('17px', $('error_test_ul').getStyle('margin-right'));
assertEqual('40px', $('error_test_ul').getStyle('font-size'));
assertEqual('#ffffff', $('error_message_2').getStyle('background-color').parseColor());
assertEqual('20px', $('error_message_2').getStyle('font-size'));
assertEqual('italic', $('error_message_3').getStyle('font-style'));
assertEqual('20px', $('error_message_3').getStyle('font-size'));
assertEqual(.5, $('error_message_3').getStyle('opacity'));
assertEqual('', $('error_message_3').style.fontSize);
});
}},
testElementMorphChaining: function() { with(this) {
$('error_message').morph('font-size:17px').morph('opacity:0',{delay:3});
wait(4100,function(){ // 3000ms delay + 1000ms default duration
assertEqual(0, $('error_message').getOpacity());
});
}},
testTransformBySelector: function() { with(this) {
new Effect.Transform([
{ 'ul.error-list li': 'font-size:20px;text-indent:40pt' }
],{ duration: 0.5 }).play();
wait(700,function(){
var idx = 0;
$A($('error_test_ul').cleanWhitespace().childNodes).each(function(node){
assertEqual('20px', $(node).getStyle('font-size'));
assertEqual('40pt', $(node).getStyle('text-indent'));
idx++;
});
assertEqual(5, idx);
});
}},
testTransformUsesCSSClassPresets: function() { with(this) {
assertEqual('40px', $('rotfl').getStyle('font-size'));
// Render the effect at half-way through, font-size should be
// exactly half-way between original and target
new Effect.Transform([
{ 'rotfl': 'font-size:20px;text-indent:40pt;background-color:#888' }
],{ sync:true }).play().render(0.5);
wait(1100,function(){
// shoould be 30px = 40px + (20px-40px)/2
assertEqual('30px', $('rotfl').getStyle('font-size'));
});
}},
testTransformMultiple: function() { with(this) {
var transformation = new Effect.Transform([
{ 'div.morphing': 'font-size:20px;padding-left:40em;opacity:0.5' },
{ 'blah' :
'width:480px;border-width:10px;border-right-width:20px;' +
'margin:20px;margin-bottom:-20px;font-size:30px;' +
'background:#954' }
],{ duration: 0.5 });
var generatedEffect = transformation.play();
assertEqual(3, generatedEffect.effects.length);
wait(700, function(){
// have a look at the generated color transforms for the 3rd found element
// which is the "blah" div
assertEqual('blah', generatedEffect.effects[2].element.id);
assertEnumEqual([255,255,255],
generatedEffect.effects[2].transforms.detect( function(transform){
return (transform.style == 'backgroundColor')
}).originalValue);
assertEnumEqual([153,85,68],
generatedEffect.effects[2].transforms.detect( function(transform){
return (transform.style == 'backgroundColor')
}).targetValue);
assertEqual('20px', $$('div.morphing').first().getStyle('font-size'));
assertEqual('20px', $$('div.morphing').last().getStyle('font-size'));
assertEqual('30px', $('blah').getStyle('font-size'));
// border-width/border-right-width should be set independently
assertEqual('10px', $('blah').getStyle('border-top-width'));
assertEqual('10px', $('blah').getStyle('border-bottom-width'));
assertEqual('10px', $('blah').getStyle('border-left-width'));
assertEqual('20px', $('blah').getStyle('border-right-width'));
// colors should assume transition from
// #ffffff (white) if original was transparent
// we now should have arrived at the given color
assertEqual('#995544', $('blah').getStyle('background-color').parseColor());
// play again = should have same values
transformation.play();
wait(700, function(){
assertEqual('20px', $$('div.morphing').first().getStyle('font-size'));
assertEqual('20px', $$('div.morphing').last().getStyle('font-size'));
assertEqual('30px', $('blah').getStyle('font-size'));
$('blah').setStyle({'font-size':'100px'});
assertEqual('100px', $('blah').getStyle('font-size'));
transformation.play();
wait(700, function(){
assertEqual('30px', $('blah').getStyle('font-size'));
new Effect.Transform([
{ 'blah': 'color: #80d980; background: #208020' }
],{ duration: 1.1 }).play();
wait(1500, function(){
assertEqual('#80d980', $('blah').getStyle('color').parseColor());
assertEqual('#208020', $('blah').getStyle('background-color').parseColor());
});
});
});
});
}}
});
// ]]>

View File

@ -148,7 +148,7 @@ bool
ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
InfallibleTArray<EditReply>* reply)
{
MOZ_LAYERS_LOG(("[ParentSide] recieved txn with %d edits", cset.Length()));
MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length()));
if (mDestroyed || layer_manager()->IsDestroyed()) {
return true;

View File

@ -462,6 +462,10 @@ static JS_ALWAYS_INLINE jsval_layout
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
{
jsval_layout l;
// Happens if XPConnect hands out an illegal value (constructed from C++ through a PRBool, for
// instance).
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
l.s.tag = JSVAL_TAG_BOOLEAN;
l.s.payload.boo = b;
return l;
@ -654,6 +658,10 @@ static JS_ALWAYS_INLINE jsval_layout
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
{
jsval_layout l;
// Happens if XPConnect hands out an illegal value (constructed from C++ through a PRBool, for
// instance).
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
l.asBits = ((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
return l;
}

View File

@ -1199,7 +1199,9 @@ DocumentViewerImpl::PermitUnload(PRBool aCallerClosesWindow, PRBool *aPermitUnlo
return NS_OK;
}
PRBool dummy;
// Although the exact value is ignored, we must not pass invalid
// PRBool values through XPConnect.
PRBool dummy = PR_FALSE;
PRInt32 buttonPressed = 0;
PRUint32 buttonFlags = (nsIPrompt::BUTTON_POS_0_DEFAULT |
(nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) |

View File

@ -93,6 +93,9 @@
#include "nsDOMFile.h"
#include "nsEventStates.h"
#include "nsIDOMDOMStringList.h"
#include "nsIDOMDragEvent.h"
namespace dom = mozilla::dom;
#define SYNC_TEXT 0x1
@ -136,6 +139,15 @@ nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
mTextFrame = nsnull;
ENSURE_TRUE(mContent);
// Remove the drag events
nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
if (dragTarget) {
dragTarget->RemoveEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, PR_FALSE);
dragTarget->RemoveEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, PR_FALSE);
}
// remove mMouseListener as a mouse event listener (bug 40533, bug 355931)
NS_NAMED_LITERAL_STRING(click, "click");
@ -258,6 +270,14 @@ nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
if (!aElements.AppendElement(mTextContent))
return NS_ERROR_OUT_OF_MEMORY;
// Register the whole frame as an event listener of drag events
nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
NS_ENSURE_STATE(dragTarget);
dragTarget->AddEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, PR_FALSE);
dragTarget->AddEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, PR_FALSE);
NS_NAMED_LITERAL_STRING(click, "click");
nsCOMPtr<nsIDOMEventGroup> systemGroup;
mContent->GetSystemEventGroup(getter_AddRefs(systemGroup));
@ -498,6 +518,74 @@ nsFileControlFrame::BrowseMouseListener::MouseClick(nsIDOMEvent* aMouseEvent)
return input ? input->FireAsyncClickHandler() : NS_OK;
}
/**
* This is called when we receive any registered events on the control.
* We've only registered for drop, dragover and click events, and click events
* already call MouseClick() for us. Here, we handle file drops.
*/
NS_IMETHODIMP
nsFileControlFrame::BrowseMouseListener::HandleEvent(nsIDOMEvent* aEvent)
{
NS_ASSERTION(mFrame, "We should have been unregistered");
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aEvent);
NS_ENSURE_STATE(uiEvent);
PRBool defaultPrevented = PR_FALSE;
uiEvent->GetPreventDefault(&defaultPrevented);
if (defaultPrevented) {
return NS_OK;
}
nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
if (!dragEvent || !IsValidDropData(dragEvent)) {
return NS_OK;
}
nsAutoString eventType;
aEvent->GetType(eventType);
if (eventType.EqualsLiteral("dragover")) {
// Prevent default if we can accept this drag data
aEvent->PreventDefault();
return NS_OK;
}
if (eventType.EqualsLiteral("drop")) {
aEvent->StopPropagation();
aEvent->PreventDefault();
nsIContent* content = mFrame->GetContent();
NS_ASSERTION(content, "The frame has no content???");
nsHTMLInputElement* inputElement = nsHTMLInputElement::FromContent(content);
NS_ASSERTION(inputElement, "No input element for this file upload control frame!");
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
nsCOMPtr<nsIDOMFileList> fileList;
dataTransfer->GetFiles(getter_AddRefs(fileList));
inputElement->SetFiles(fileList, true);
}
return NS_OK;
}
/* static */ PRBool
nsFileControlFrame::BrowseMouseListener::IsValidDropData(nsIDOMDragEvent* aEvent)
{
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
aEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
NS_ENSURE_TRUE(dataTransfer, PR_FALSE);
nsCOMPtr<nsIDOMDOMStringList> types;
dataTransfer->GetTypes(getter_AddRefs(types));
NS_ENSURE_TRUE(types, PR_FALSE);
// We only support dropping files onto a file upload control
PRBool typeSupported;
types->Contains(NS_LITERAL_STRING("Files"), &typeSupported);
return typeSupported;
}
nscoord
nsFileControlFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
{

View File

@ -48,6 +48,8 @@
#include "nsTextControlFrame.h"
typedef nsTextControlFrame nsNewFrame;
class nsIDOMDragEvent;
class nsFileControlFrame : public nsBlockFrame,
public nsIFormControlFrame,
public nsIAnonymousContentCreator
@ -169,6 +171,9 @@ protected:
public:
BrowseMouseListener(nsFileControlFrame* aFrame) : MouseListener(aFrame) {};
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
static PRBool IsValidDropData(nsIDOMDragEvent* aEvent);
};
virtual PRBool IsFrameOfType(PRUint32 aFlags) const

View File

@ -68,6 +68,7 @@ EXPORTS = \
nsIStatefulFrame.h \
nsFrameSelection.h \
nsSubDocumentFrame.h \
nsObjectFrame.h \
$(NULL)
ifdef IBMBIDI

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,7 @@
#include <windows.h>
#endif
#include "nsPluginInstanceOwner.h"
#include "nsIObjectFrame.h"
#include "nsFrame.h"
#include "nsRegion.h"
@ -56,11 +57,9 @@
class nsIAccessible;
#endif
class nsPluginInstanceOwner;
class nsPluginHost;
class nsPresContext;
class nsDisplayPlugin;
class nsIDOMElement;
class nsIOSurface;
class PluginBackgroundSink;

View File

@ -1392,7 +1392,7 @@ var FullScreenVideo = {
this._dispatchMouseEvent("Browser:MouseDown", aEvent.clientX, aEvent.clientY);
break;
case "TapSingle":
this._dispatchMouseEvent("Browser:MouseUp", aEvent.clientX, aEvent.clientY);
this._dispatchMouseEvent("Browser:MouseClick", aEvent.clientX, aEvent.clientY);
break;
}
},

View File

@ -13,13 +13,15 @@
<binding id="stacked-notificationbox" extends="chrome://global/content/bindings/notification.xml#notificationbox">
<content>
<xul:stack xbl:inherits="hidden=notificationshidden">
<xul:spacer/>
<children includes="notification"/>
</xul:stack>
<xul:stack flex="1">
<children/>
<html:div flex="1" class="input-overlay" anonid="input-overlay"/>
<xul:stack>
<xul:stack top="0">
<children/>
<html:div flex="1" class="input-overlay" anonid="input-overlay"/>
</xul:stack>
<xul:stack top="0" xbl:inherits="hidden=notificationshidden">
<xul:spacer/>
<children includes="notification"/>
</xul:stack>
</xul:stack>
</content>
<implementation>

View File

@ -75,7 +75,7 @@ toolbarbutton.urlbar-button {
}
#tool-app-switch:hover:active {
background-color: #8db8d8 !important;
background-color: @color_background_highlight@ !important;
-moz-border-radius-bottomright: @border_radius_small@;
}
@ -96,7 +96,7 @@ toolbarbutton.urlbar-button {
}
#tool-app-close:hover:active {
background-color: #8db8d8 !important;
background-color: @color_background_highlight@ !important;
}
#tool-app-close:hover:active:-moz-locale-dir(ltr) {
@ -202,7 +202,7 @@ toolbarbutton.urlbar-button {
}
#urlbar-title.placeholder {
color: gray;
color: @color_text_placeholder@;
}
#urlbar-edit,
@ -349,7 +349,7 @@ toolbarbutton.button-control:not([disabled="true"]):hover:active {
}
.panel-close:hover:active {
background-color: #8db8d8 !important;
background-color: @color_background_highlight@ !important;
}
.panel-close:hover:active:-moz-locale-dir(ltr) {
@ -395,7 +395,7 @@ remotetabslist > hbox.remotetabs-throbber-box {
historylist[loading="true"] > hbox.history-throbber-box,
remotetabslist[loading="true"] > hbox.remotetabs-throbber-box {
background-color: white;
background-color: white; /* force */
display: -moz-box;
}
@ -515,12 +515,9 @@ remotetabslist[loading="true"] > richlistbox.remotetabs-list-children {
-moz-margin-end: @margin_normal@;
}
richlistitem[isDisabled="true"] .title {
color: gray;
}
richlistitem[isDisabled="true"] .title,
richlistitem[isDisabled="true"] .normal {
color: lightgray;
color: @color_text_disabled@;
}
richlistitem[isDisabled="true"] image {
@ -550,7 +547,7 @@ richlistitem[isDisabled="true"] image {
#dl-empty-message > label {
text-align: center;
color: grey;
color: @color_text_placeholder@;
}
/* console panel UI ------------------------------------------------------ */
@ -588,7 +585,7 @@ placelabel {
background-repeat: no-repeat, repeat-x;
background-position: 98% 50%, top left;
background-size: auto auto, auto 100%;
color: #000;
color: black; /* force */
min-height: @touch_row@; /* row size */
}
@ -598,7 +595,8 @@ placelabel:-moz-locale-dir(rtl) {
placelabel:hover:active {
background-image: url(images/arrowup-16.png);
background-color: #8db8d8;
background-color: @color_background_highlight@;
color: @color_text_highlight@;
}
/* folder bookmarks row */
@ -648,16 +646,19 @@ placeitem[ui="manage"] > .bookmark-manage textbox[anonid="uri"]:-moz-locale-dir(
text-align: right;
}
/* autocomplete-items */
.autocomplete-items {
background-color: white;
/* force the richlistboxes to have a white background */
.autocomplete-items,
.place-list-children,
.history-list-children,
.remotetabs-list-children {
background-color: white; /* force */
}
autocompleteresult,
placeitem {
-moz-user-focus: ignore;
color: black;
background-color: white;
color: black; /* force */
background-color: white; /* force */
padding: @padding_xsmall@ @padding_small@;
border-bottom: @border_width_tiny@ solid rgb(207,207,207);
min-height: @touch_row@; /* row size */
@ -668,7 +669,8 @@ placelist placeitem:hover:active:not([selected="true"]),
historylist autocompleteresult:hover:active:not([selected="true"]):not([class="history-item-title"]),
remotetabslist autocompleteresult:hover:active:not([selected="true"]):not([class="remotetabs-item-title"]),
.autocompleteresult-selected {
background-color: #8db8d8;
background-color: @color_background_highlight@;
color: @color_text_highlight@;
}
.autocomplete-item-container,
@ -747,7 +749,7 @@ placeitem[src=""] .bookmark-item-container > image {
.autocomplete-item-subtitle,
.bookmark-item-url {
color: blue;
color: blue; /* force */
font-size: @font_small@ !important;
-moz-margin-end: @autocomplete_item_subtitle_margin@;
}
@ -759,8 +761,7 @@ placeitem[src=""] .bookmark-item-container > image {
}
.autocomplete-item-container[search="true"] .autocomplete-item-subtitle {
color: black;
font-size: smaller;
color: black; /* force */
}
.autocomplete-item-tags,
@ -853,12 +854,12 @@ autocompleteresult.noresults {
}
autocompleteresult.noresults:hover:active {
background-color: white !important;
background-color: white !important; /* force */
}
autocompleteresult.noresults > .autocomplete-item-container {
text-align: center;
color: grey;
color: @color_text_placeholder@;
}
/* Left sidebar (tabs) ---------------------------------------------------- */
@ -1053,6 +1054,7 @@ documenttab[reload="true"] > stack > .documenttab-reload {
.action-button,
.context-command,
pageaction {
color: black; /* force */
-moz-border-top-colors: white;
-moz-border-right-colors: rgb(175,175,175);
-moz-border-bottom-colors: rgb(175,175,175);
@ -1078,7 +1080,7 @@ pageaction {
.action-button[disabled="true"],
.context-command[disabled="true"] {
pointer-events: none;
color: #aaa !important;
color: @color_text_disabled@ !important;
}
.action-button[selected="true"],
@ -1117,7 +1119,9 @@ pageaction {
.action-button:not([disabled]):hover:active,
.context-command:not([disabled]):hover:active,
pageaction:not([disabled]):hover:active {
background: url("chrome://browser/skin/images/popup-selected-item-hdpi.png") repeat-x !important;
color: @color_text_highlight@;
background-color: @color_background_highlight@;
background-image: none !important;
background-origin: border-box !important;
background-clip: border-box !important;
-moz-border-top-colors: transparent;
@ -1138,12 +1142,11 @@ pageaction:not([image]) > hbox >.pageaction-image {
.context-command,
.pageaction-title {
font-size: @font_normal@ !important;
color: #414141 !important;
}
.pageaction-desc {
font-size: @font_tiny@ !important;
color: #414141;
color: @color_subtext_inverse@;
}
.pageaction-desc[value=""] {
@ -1243,12 +1246,12 @@ pageaction:not([image]) > hbox >.pageaction-image {
/* XXX should be a richlistitem description.normal */
.prefdesc {
font-size: @font_small@ !important;
color: grey;
color: @color_subtext_default@;
}
/* alerts popup ----------------------------------------------------------- */
#alerts-container {
color: white;
color: @color_text_default@;
background-color: #5e6166;
border: @border_width_small@ solid #767973;
border-radius: @border_radius_normal@;
@ -1412,8 +1415,8 @@ pageaction:not([image]) > hbox >.pageaction-image {
}
.syncsetup-code {
color: #000;
background-color: #fff;
color: @color_text_inverse@;
background-color: @color_background_inverse@;
font-size: @font_xlarge@ !important;
padding: 0.2em 0.4em;
-moz-padding-end: 0.2em;
@ -1427,7 +1430,7 @@ pageaction:not([image]) > hbox >.pageaction-image {
}
.syncsetup-label {
color: #fff;
color: @color_text_default@;
}
#syncsetup-customserver {

View File

@ -44,7 +44,7 @@
/* make clicking on links stand out a bit (bug 532206) */
* > *:not(embed):focus, * > *:focus > font {
outline: 2px solid #8db8d8 !important;
outline: 2px solid @color_background_highlight@ !important;
/*
XXX How do I preserve mac focusring without blowing focus color on other platforms?
outline-color: -moz-mac-focusring !important;
@ -344,7 +344,7 @@ option:active,
select:active,
label:active,
textarea:active {
background-color: rgba(141, 184, 216, 0.5) !important;
background-color: @color_background_highlight_overlay@ !important;
}
/*

View File

@ -11,10 +11,18 @@
%define color_background_header #292929
%define color_text_header #999999
%define color_background_scroller #9a9a9a
%define color_background_inverse #fff
%define color_text_inverse #000
%define color_text_gray #808080
%define color_text_button #000
%define color_text_disabled #808080
%define color_text_placeholder #808080
%define color_background_highlight #febc2b
%define color_background_highlight_overlay rgba(254, 188, 43, 0.8)
%define color_text_highlight #000
%define color_subtext_default lightgray
%define color_subtext_inverse #414141
%ifdef ANDROID
%define font_xlarge 5.08mozmm

View File

@ -48,8 +48,8 @@
}
::-moz-selection {
background-color: #8db8d8;
color: black;
background-color: @color_background_highlight@;
color: @color_text_highlight@;
}
menu,
@ -82,7 +82,7 @@ textbox:not([type="number"]) {
}
textbox[isempty="true"] {
color: @color_text_gray@;
color: @color_text_placeholder@;
}
textbox.search-bar {
@ -146,7 +146,7 @@ button {
-moz-appearance: none;
min-width: @touch_button_minwidth@ !important;
min-height: @touch_button_small@ !important; /* button size */
color: #000;
color: @color_text_button@;
margin: @margin_normal@;
padding: @padding_xnormal@;
background-image: url("chrome://browser/skin/images/button-bg.png");
@ -155,7 +155,7 @@ button {
}
button[disabled="true"] {
color: #aaa !important;
color: @color_text_disabled@ !important;
border: @border_width_tiny@ solid @color_button_border@ !important;
}
@ -207,7 +207,7 @@ spinbuttons {
-moz-appearance: none !important;
min-width: @touch_button_small@ !important; /* button size */
min-height: @touch_button_small@ !important; /* button size */
color: #000;
color: @color_text_button@;
margin: @margin_normal@;
padding: @padding_xnormal@;
background-image: url("chrome://browser/skin/images/button-bg.png");
@ -261,7 +261,7 @@ toolbarbutton[open="true"] {
background: none !important;
border: none !important;
-moz-border-image: none !important;
color: white;
color: @color_text_default@;
-moz-box-align: center;
font-size: @font_small@;
-moz-box-align: center;
@ -302,7 +302,7 @@ radio {
-moz-appearance: none;
min-width: @touch_button_small@ !important; /* button size */
min-height: @touch_button_small@ !important; /* button size */
color: #000;
color: @color_text_button@;
padding: @padding_xnormal@;
margin: 0;
background-image: url("chrome://browser/skin/images/button-bg.png");
@ -395,7 +395,7 @@ richlistitem description.title {
richlistitem label.normal,
richlistitem description.normal {
color: gray;
color: @color_subtext_default@;
font-size: @font_small@ !important;
white-space: pre-wrap;
word-wrap: break-word;
@ -421,8 +421,11 @@ richlistitem[selected="true"] {
background-color: @color_background_default@;
}
richlistitem:hover:active:not([selected="true"]):not([nohighlight="true"]) {
background-color: #8db8d8;
richlistitem:hover:active:not([selected="true"]):not([nohighlight="true"]),
richlistitem:hover:active:not([selected="true"]):not([nohighlight="true"]) label.normal,
richlistitem:hover:active:not([selected="true"]):not([nohighlight="true"]) description.normal {
background-color: @color_background_highlight@;
color: @color_text_highlight@;
}
richlistitem.section-header,
@ -485,7 +488,7 @@ menulist {
-moz-user-focus: ignore;
min-width: @touch_button_minwidth@ !important;
min-height: @touch_button_small@ !important; /* button size */
color: #000 !important;
color: @color_text_button@ !important;
margin: @margin_normal@;
padding: @padding_small@ @padding_xnormal@;
background-image: url("chrome://browser/skin/images/button-bg.png");
@ -494,7 +497,7 @@ menulist {
}
menulist[disabled="true"] {
color: #aaa !important;
color: @color_text_disabled@ !important;
border: @border_width_tiny@ solid @color_button_border@ !important;
}
@ -532,7 +535,7 @@ progressmeter {
}
.progress-bar {
background-color: #8db8d8;
background-color: @color_background_highlight@;
}
/* panels / arrowboxes------------------------------------------------------ */
@ -687,7 +690,7 @@ dialog {
}
.panel-row-button[disabled="true"] .toolbarbutton-text {
color: #aaa;
color: @color_text_disabled@;
}
.panel-row-button[checked="true"] {

View File

@ -680,19 +680,23 @@ RasterImage::GetFrame(PRUint32 aWhichFrame,
nsresult rv = NS_OK;
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
if (desiredDecodeFlags != mFrameDecodeFlags) {
// if we can't discard, then we're screwed; we have no way
// to re-decode. Similarly if we aren't allowed to do a sync
// decode.
if (!(aFlags & FLAG_SYNC_DECODE))
return NS_ERROR_NOT_AVAILABLE;
if (!CanForciblyDiscard() || mDecoder || mAnim)
return NS_ERROR_NOT_AVAILABLE;
ForceDiscard();
mFrameDecodeFlags = desiredDecodeFlags;
if (mDecoded) {
// If we have decoded data, and it is not a perfect match for what we are
// looking for, we must discard to be able to generate the proper data.
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
if (desiredDecodeFlags != mFrameDecodeFlags) {
// if we can't discard, then we're screwed; we have no way
// to re-decode. Similarly if we aren't allowed to do a sync
// decode.
if (!(aFlags & FLAG_SYNC_DECODE))
return NS_ERROR_NOT_AVAILABLE;
if (!CanForciblyDiscard() || mDecoder || mAnim)
return NS_ERROR_NOT_AVAILABLE;
ForceDiscard();
mFrameDecodeFlags = desiredDecodeFlags;
}
}
// If the caller requested a synchronous decode, do it

View File

@ -144,6 +144,14 @@
#define NS_ERROR_INVALID_CONTENT_ENCODING \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 27)
/**
* A transport level corruption was found in the source document. for example
* a document with a calculated checksum that does not match the Content-MD5
* http header.
*/
#define NS_ERROR_CORRUPTED_CONTENT \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 29)
/******************************************************************************
* Connectivity error codes:
*/

View File

@ -137,7 +137,8 @@ nsHttpChunkedDecoder::ParseChunkRemaining(char *buf,
LOG(("got trailer: %s\n", buf));
// allocate a header array for the trailers on demand
if (!mTrailers) {
mTrailers = new nsHttpHeaderArray();
mTrailers = new nsHttpHeaderArray
(nsHttpHeaderArray::HTTP_RESPONSE_HEADERS);
if (!mTrailers)
return NS_ERROR_OUT_OF_MEMORY;
}

View File

@ -85,8 +85,11 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
entry->value.Append(value);
}
// Replace the existing string with the new value
else
else if (CanOverwriteHeader(header))
entry->value = value;
else if (!entry->value.Equals(value))
return NS_ERROR_CORRUPTED_CONTENT;
return NS_OK;
}
@ -129,7 +132,7 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor)
return NS_OK;
}
void
nsresult
nsHttpHeaderArray::ParseHeaderLine(const char *line,
nsHttpAtom *hdr,
char **val)
@ -151,13 +154,13 @@ nsHttpHeaderArray::ParseHeaderLine(const char *line,
char *p = (char *) strchr(line, ':');
if (!p) {
LOG(("malformed header [%s]: no colon\n", line));
return;
return NS_OK;
}
// make sure we have a valid token for the field-name
if (!nsHttp::IsValidToken(line, p)) {
LOG(("malformed header [%s]: field-name not a token\n", line));
return;
return NS_OK;
}
*p = 0; // null terminate field-name
@ -165,7 +168,7 @@ nsHttpHeaderArray::ParseHeaderLine(const char *line,
nsHttpAtom atom = nsHttp::ResolveAtom(line);
if (!atom) {
LOG(("failed to resolve atom [%s]\n", line));
return;
return NS_OK;
}
// skip over whitespace
@ -183,7 +186,7 @@ nsHttpHeaderArray::ParseHeaderLine(const char *line,
if (val) *val = p;
// assign response header
SetHeader(atom, nsDependentCString(p, p2 - p), PR_TRUE);
return SetHeader(atom, nsDependentCString(p, p2 - p), PR_TRUE);
}
void
@ -247,3 +250,11 @@ nsHttpHeaderArray::CanAppendToHeader(nsHttpAtom header)
header != nsHttp::Location &&
header != nsHttp::Max_Forwards;
}
PRBool
nsHttpHeaderArray::CanOverwriteHeader(nsHttpAtom header)
{
if (mType != HTTP_RESPONSE_HEADERS)
return PR_TRUE;
return header != nsHttp::Content_Length;
}

View File

@ -49,7 +49,12 @@
class nsHttpHeaderArray
{
public:
nsHttpHeaderArray() {}
enum nsHttpHeaderType {
HTTP_REQUEST_HEADERS,
HTTP_RESPONSE_HEADERS
};
nsHttpHeaderArray(nsHttpHeaderType headerType) : mType(headerType) {}
~nsHttpHeaderArray() { Clear(); }
const char *PeekHeader(nsHttpAtom header);
@ -73,9 +78,9 @@ public:
// parse a header line, return the header atom and a pointer to the
// header value (the substring of the header line -- do not free).
void ParseHeaderLine(const char *line,
nsHttpAtom *header=nsnull,
char **value=nsnull);
nsresult ParseHeaderLine(const char *line,
nsHttpAtom *header=nsnull,
char **value=nsnull);
void Flatten(nsACString &, PRBool pruneProxyHeaders=PR_FALSE);
@ -104,8 +109,10 @@ public:
private:
PRInt32 LookupEntry(nsHttpAtom header, nsEntry **);
PRBool CanAppendToHeader(nsHttpAtom header);
PRBool CanOverwriteHeader(nsHttpAtom header);
nsTArray<nsEntry> mHeaders;
nsHttpHeaderType mType;
};
#endif

View File

@ -52,8 +52,10 @@
class nsHttpRequestHead
{
public:
nsHttpRequestHead() : mMethod(nsHttp::Get), mVersion(NS_HTTP_VERSION_1_1) {}
~nsHttpRequestHead() {}
nsHttpRequestHead() : mHeaders(nsHttpHeaderArray::HTTP_REQUEST_HEADERS)
, mMethod(nsHttp::Get)
, mVersion(NS_HTTP_VERSION_1_1) {}
~nsHttpRequestHead() {}
void SetMethod(nsHttpAtom method) { mMethod = method; }
void SetVersion(nsHttpVersion version) { mVersion = version; }

View File

@ -197,23 +197,30 @@ nsHttpResponseHead::ParseStatusLine(const char *line)
PRUintn(mVersion), PRUintn(mStatus), mStatusText.get()));
}
void
nsresult
nsHttpResponseHead::ParseHeaderLine(const char *line)
{
nsHttpAtom hdr = {0};
char *val;
mHeaders.ParseHeaderLine(line, &hdr, &val);
nsresult rv;
rv = mHeaders.ParseHeaderLine(line, &hdr, &val);
if (NS_FAILED(rv))
return rv;
// leading and trailing LWS has been removed from |val|
// handle some special case headers...
if (hdr == nsHttp::Content_Length) {
PRInt64 len;
// permit only a single value here.
if (nsHttp::ParseInt64(val, &len))
if (nsHttp::ParseInt64(val, &len)) {
mContentLength = len;
else
}
else {
LOG(("invalid content-length!\n"));
return NS_ERROR_CORRUPTED_CONTENT;
}
}
else if (hdr == nsHttp::Content_Type) {
LOG(("ParseContentType [type=%s]\n", val));
@ -225,6 +232,7 @@ nsHttpResponseHead::ParseHeaderLine(const char *line)
ParseCacheControl(val);
else if (hdr == nsHttp::Pragma)
ParsePragma(val);
return NS_OK;
}
// From section 13.2.3 of RFC2616, we compute the current age of a cached

View File

@ -51,13 +51,14 @@
class nsHttpResponseHead
{
public:
nsHttpResponseHead() : mVersion(NS_HTTP_VERSION_1_1)
nsHttpResponseHead() : mHeaders(nsHttpHeaderArray::HTTP_RESPONSE_HEADERS)
, mVersion(NS_HTTP_VERSION_1_1)
, mStatus(200)
, mContentLength(LL_MAXUINT)
, mCacheControlNoStore(PR_FALSE)
, mCacheControlNoCache(PR_FALSE)
, mPragmaNoCache(PR_FALSE) {}
~nsHttpResponseHead()
~nsHttpResponseHead()
{
Reset();
}
@ -104,7 +105,7 @@ public:
void ParseStatusLine(const char *line);
// parse a header line. line must be null terminated. parsing is destructive.
void ParseHeaderLine(const char *line);
nsresult ParseHeaderLine(const char *line);
// cache validation support methods
nsresult ComputeFreshnessLifetime(PRUint32 *);

View File

@ -784,12 +784,12 @@ nsHttpTransaction::LocateHttpStart(char *buf, PRUint32 len,
return 0;
}
void
nsresult
nsHttpTransaction::ParseLine(char *line)
{
LOG(("nsHttpTransaction::ParseLine [%s]\n", line));
nsresult rv = NS_OK;
if (!mHaveStatusLine) {
mResponseHead->ParseStatusLine(line);
mHaveStatusLine = PR_TRUE;
@ -797,8 +797,10 @@ nsHttpTransaction::ParseLine(char *line)
if (mResponseHead->Version() == NS_HTTP_VERSION_0_9)
mHaveAllHeaders = PR_TRUE;
}
else
mResponseHead->ParseHeaderLine(line);
else {
rv = mResponseHead->ParseHeaderLine(line);
}
return rv;
}
nsresult
@ -813,8 +815,11 @@ nsHttpTransaction::ParseLineSegment(char *segment, PRUint32 len)
// of mLineBuf.
mLineBuf.Truncate(mLineBuf.Length() - 1);
if (!mHaveStatusLine || (*segment != ' ' && *segment != '\t')) {
ParseLine(mLineBuf.BeginWriting());
nsresult rv = ParseLine(mLineBuf.BeginWriting());
mLineBuf.Truncate();
if (NS_FAILED(rv)) {
return rv;
}
}
}

View File

@ -141,7 +141,7 @@ private:
nsresult Restart();
char *LocateHttpStart(char *buf, PRUint32 len,
PRBool aAllowPartialMatch);
void ParseLine(char *line);
nsresult ParseLine(char *line);
nsresult ParseLineSegment(char *seg, PRUint32 len);
nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead);
nsresult HandleContentStart();

View File

@ -807,7 +807,9 @@ PK11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg) {
rv = NS_ERROR_NOT_AVAILABLE;
}
else {
PRBool checkState;
// Although the exact value is ignored, we must not pass invalid
// PRBool values through XPConnect.
PRBool checkState = PR_FALSE;
rv = proxyPrompt->PromptPassword(nsnull, promptString.get(),
&password, nsnull, &checkState, &value);
}

View File

@ -7217,7 +7217,7 @@ DirectoryInstallLocation.prototype = {
linkedDirectory.initWithPath(line.value);
}
catch (e) {
linkedDirectory.setRelativeDescriptor(file.parent, line.value);
linkedDirectory.setRelativeDescriptor(aFile.parent, line.value);
}
if (!linkedDirectory.exists()) {

View File

@ -64,6 +64,25 @@ function writePointer(aId, aName) {
fos.close();
}
function writeRelativePointer(aId, aName) {
let file = profileDir.clone();
file.append(aName ? aName : aId);
let absTarget = sourceDir.clone();
absTarget.append(do_get_expected_addon_name(aId));
var relTarget = absTarget.QueryInterface(Ci.nsILocalFile)
.getRelativeDescriptor(profileDir);
var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(AM_Ci.nsIFileOutputStream);
fos.init(file,
FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE,
FileUtils.PERMS_FILE, 0);
fos.write(relTarget, relTarget.length);
fos.close();
}
function run_test() {
// pointer files only work with unpacked directories
if (Services.prefs.getBoolPref("extensions.alwaysUnpack") == false)
@ -352,7 +371,33 @@ function run_test_9() {
pointer.append(addon1.id);
do_check_false(pointer.exists());
end_test();
run_test_10();
});
});
}
// Tests that installing a new add-on by pointer with a relative path works
function run_test_10() {
writeInstallRDFForExtension(addon1, sourceDir);
writeRelativePointer(addon1.id);
restartManager();
AddonManager.getAddonByID(addon1.id, function(a1) {
do_check_neq(a1, null);
do_check_eq(a1.version, "1.0");
let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file;
do_check_eq(file.parent.path, sourceDir.path);
let rootUri = do_get_addon_root_uri(sourceDir, addon1.id);
let uri = a1.getResourceURI("/");
do_check_eq(uri.spec, rootUri);
uri = a1.getResourceURI("install.rdf");
do_check_eq(uri.spec, rootUri + "install.rdf");
// Check that upgrade is disabled for addons installed by file-pointers.
do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0);
end_test();
});
}

View File

@ -619,7 +619,7 @@ else
endif # DMG
endif # MOZ_PKG_MANIFEST
endif # UNIVERSAL_BINARY
$(OPTIMIZE_JARS_CMD) --optimize $(JARLOG_DIR) $(DIST)/bin/chrome $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)/chrome
$(OPTIMIZE_JARS_CMD) --optimize $(JARLOG_DIR) $(DIST)/bin/chrome $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/chrome
ifndef PKG_SKIP_STRIP
ifeq ($(OS_ARCH),OS2)
@echo "Stripping package directory..."

View File

@ -56,7 +56,7 @@ notification[type="critical"] .messageImage {
/* Popup notification */
.popup-notification-description {
max-width: 248px;
max-width: 24em;
}
.popup-notification-button-container {

View File

@ -91,7 +91,7 @@ notification[type="warning"] .messageCloseButton {
/* Popup notification */
.popup-notification-description {
max-width: 248px;
max-width: 24em;
}
.popup-notification-button-container {

View File

@ -60,7 +60,7 @@ notification[type="critical"] .messageImage {
/* Popup notification */
.popup-notification-description {
max-width: 248px;
max-width: 24em;
}
.popup-notification-button-container {