Compare commits

...
Author SHA1 Message Date
wolfbeast 329d35ab57 Merge branch 'release' into Basilisk-release 2020-01-11 22:41:59 +01:00
wolfbeast cffb44547a Simplify some alias sets in IonMonkey. 2020-01-11 13:50:23 +01:00
wolfbeast 81f3185e0e Prefer file extension as-provided over default extension for mimetype to
look up default applications on Windows
2020-01-11 13:50:08 +01:00
wolfbeast e01d499617 Update GTK clipboard handling
- Store the clipboard even if it was set in a GTK dialog.
- Fix a GtkTargetList leak.
- Notify GTK that the data is no longer available for
clipboard_get_cb(), so that GTK will no longer advertise nor attempt to
store the data.
2020-01-11 13:49:49 +01:00
wolfbeast 38b0041414 Handle missing base64 challenge in NegotiateAuth and NTLMAuth. 2020-01-11 13:46:18 +01:00
Yaron Tausky d62795c868 Make copy of list before iterating over it. 2020-01-11 13:46:03 +01:00
wolfbeast d0256e1afc Be more consistent about decoding IP addresses in PSM. 2020-01-11 13:45:47 +01:00
wolfbeast 19939f17f0 Simplify value setting.
This gets rid of unused boolean return values on setters and a level of
indirection for calls to set values.
2020-01-11 13:45:34 +01:00
wolfbeast 00b8ab8be2 Issue #1348 - Part 3: Set IS_PRIVATE input scope in private browsing.
Microsoft IME on Windows 10 20H1 (build 19025+) supports IME private
mode by input scope. Although previous Windows versions use an
undocumented API for Edge and IE only, the next Windows 10 release will
use a public API for it.
We pre-empt this potential privacy concern by setting the IS_PRIVATE
flag when in PB mode.
2020-01-11 13:45:17 +01:00
wolfbeast e338d99699 Issue #1348 - Part 2: Teach IMEState about Private Browsing mode. 2020-01-11 13:45:02 +01:00
Makoto Kato f61a99e5ed Issue #1348 - Part 1: Clean up input scope support for IMM32.
Use AutoTArray to set input scope.
2020-01-11 13:44:49 +01:00
wolfbeast f0e7aec5da Reject sample rates that are out-of-range for libsoundtouch.
We never reach this with our normal use of this lib but adding the
sanity check just in case. (ported from upstream)
2020-01-11 13:44:33 +01:00
Gaming4JC c7fbaa67c6 Bug 1599054 - allow callers to ommit sending OAuth2 client_secret parameter. 2020-01-11 13:43:26 +01:00
Gaming4JC c5b7a8f476 Bug 1597933 - Use URLSearchParams for setting params for OAuth2 authorization request. 2020-01-11 13:43:26 +01:00
Gaming4JC 686415ad89 Bug 1597933 - use fetch + URLSearchParms instead of Http.jsm to request OAuth2 access token. 2020-01-11 13:43:25 +01:00
Gaming4JC 925fd54115 Bug 1597933 - don't pass string constants to determine OAuth refresh token or not. 2020-01-11 13:43:25 +01:00
Gaming4JC c33ae6a656 Bug 1597933 - improve OAuth2 params parsing. 2020-01-11 13:43:24 +01:00
Gaming4JC 135098e064 Bug 1597933 - clean up OAuth2 code: remove responseType which is always code.
Response type token is part of the OAuth 2.0 Implicit Flow which is not used in Mail Applications, but also discouraged by the OAuth Working Group: https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead
2020-01-11 13:43:23 +01:00
Gaming4JC 1eb19e2309 Bug 1453643 - Enable proper retry on oauth2 authenication failure.
This prevents mail applications from  attempting to use an unauthenticated connection to mailbox(s) and avoid unexpected deletion of local mbox files and subsequent re-download of mailbox content over imap.
2020-01-11 13:43:23 +01:00
Gaming4JC 798cdc9e47 Bug 1176399 - Multiple requests for master password when GMail OAuth2 is enabled. 2020-01-11 13:43:22 +01:00
wolfbeast 1110944d4b Merge branch 'master' into release 2019-12-09 10:04:08 +01:00
wolfbeast 18159927e8 Merge branch 'master' into release 2019-12-07 08:47:22 +01:00
wolfbeast d0da27ef57 Merge branch 'release' into Basilisk-release 2019-10-30 18:42:38 +01:00
wolfbeast 0f7f961e88 Merge branch 'master' into Basilisk-release 2019-09-06 10:31:35 +02:00
Matt A. Tobin dba27e6f63 [MCP Applications] Add %WIDGET_TOOLKIT% to the AUS update url for Pale Moon and Basilisk
Also removes the redundant branding version of app.update.url in Pale Moon that was missed when many prefs were merged back into application preferences
2019-09-03 13:37:37 +02:00
wolfbeast 202296d02a Pull Basilisk-release forward. 2019-08-18 16:26:16 +02:00
wolfbeast 1530f48c27 Improve origin-clean algorithm based on our previous changes.
- Instead of trying the failing refactored Mozilla way, simply add a
check where needed building on what was put in place previously.
2019-06-08 19:32:47 +02:00
wolfbeast 684778cb22 Revert "Improve origin-clean algorithm"
This reverts commit e69b3f567c.
2019-06-08 19:31:36 +02:00
wolfbeast dee00a8a79 Merge branch 'master' into Basilisk-release 2019-06-04 18:21:04 +02:00
wolfbeast 851cfd198b Simplify some alias sets in IonMonkey. 2019-03-26 18:42:38 +01:00
wolfbeast 1e1525c44c Merge commit 'eb77e289bbe056b58051db0fa868e95da803aa0a' into Basilisk-release 2019-03-26 18:41:32 +01:00
wolfbeast e25ad54395 Merge branch 'master' into Basilisk-release 2019-03-06 12:30:20 +01:00
wolfbeast 74533a8432 Expose TLS 1.3 cipher suite prefs. 2019-02-10 09:00:44 +01:00
wolfbeast 7715472ae4 Merge branch 'master' into Basilisk-release 2019-02-08 13:21:03 +01:00
wolfbeast 2b3b0e053e Merge branch 'master' into Basilisk-release 2019-02-07 23:03:00 +01:00
wolfbeast e66dd9ee75 Merge branch 'master' into Basilisk-release 2019-02-07 22:18:49 +01:00
wolfbeast 0dca00b282 Merge branch 'master' into Basilisk-release 2019-02-07 16:32:52 +01:00
wolfbeast 76fe52eb81 Merge branch 'master' into Basilisk-release 2018-12-18 11:39:00 +01:00
wolfbeast 63635e38ff Merge branch 'master' into Basilisk-release 2018-11-07 06:01:03 +01:00
wolfbeast 1626b5d704 Merge branch 'master' into Basilisk-release 2018-11-03 09:06:25 +01:00
wolfbeast 314fb761d1 Merge branch 'master' into Basilisk-release 2018-09-27 09:07:52 +02:00
wolfbeast fbaab39c94 Merge branch 'master' into Basilisk-release 2018-09-27 09:05:25 +02:00
wolfbeast 580084e9e1 Merge branch 'master' into Basilisk-release 2018-09-04 20:53:31 +02:00
wolfbeast fc61780b35 Merge commit '50d3e596bbe89c95615f96eb71f6bc5be737a1db' into Basilisk-release
# Conflicts:
#	browser/app/profile/firefox.js
#	browser/components/preferences/jar.mn
2018-07-18 08:24:24 +02:00
wolfbeast 69f7f9e5f1 Pre-process blocklists.js 2018-06-01 00:46:44 +02:00
wolfbeast 2d4ff8df91 Merge branch 'master' into Basilisk-release 2018-05-31 09:45:25 +02:00
wolfbeast f4b8be889c Merge branch 'master' into Basilisk-release 2018-05-14 12:21:38 +02:00
wolfbeast e9dd029f5d Merge branch 'master' into Basilisk-release 2018-05-14 10:50:01 +02:00
wolfbeast 9d6a7ae25d Merge branch 'master' into Basilisk-release 2018-04-27 01:28:11 +02:00
wolfbeast 42f8488a5f Merge branch 'master' into Basilisk-release 2018-04-25 23:08:37 +02:00
wolfbeast 681c39a0ec Hard-code the version number for Mozilla's version checker for add-ons. 2018-04-23 17:21:17 +02:00
wolfbeast 55eb2832f5 Set preferences for release. 2018-04-22 20:41:43 +02:00
wolfbeast 003273327d Make sure to keep the safebrowsing entities valid. 2018-04-22 18:17:19 +02:00
wolfbeast 650371311d Update about:rights legal text. 2018-04-22 14:59:26 +02:00
wolfbeast 1fccd9d8ee Remove undesired system add-ons (all except PDFjs) 2018-04-22 13:19:49 +02:00
wolfbeast f2f6f7e8b0 Disable Mozilla health report service. 2018-04-22 13:16:44 +02:00
wolfbeast e73929a782 Remove NPAPI deprecation statement from about:plugins. 2018-04-22 13:08:18 +02:00
30 changed files with 492 additions and 350 deletions

No files matched your search

@@ -41,8 +41,7 @@ pref("app.update.url.details", "https://@BRANDING_SITEURL@/@BRANDING_RELNOTESPAT
pref("general.useragent.compatMode.firefox",true);
pref("general.useragent.compatMode.gecko",true);
// Switch Application Updates off for now
pref("app.update.enabled", false);
pref("app.update.enabled", true);
// Shared User Agent Overrides
#include ../../shared/uaoverrides.inc
+2 -1
View File
@@ -68,7 +68,8 @@ StreamControl::CloseAllReadStreams()
{
AssertOwningThread();
ReadStreamList::ForwardIterator iter(mReadStreamList);
auto readStreamList = mReadStreamList;
ReadStreamList::ForwardIterator iter(readStreamList);
while (iter.HasMore()) {
iter.GetNext()->CloseStream();
}
+16 -8
View File
@@ -297,7 +297,7 @@ IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nullptr, sWidget, action);
SetIMEState(newState, nullptr, nullptr, sWidget, action);
}
sWidget = nullptr;
sContent = nullptr;
@@ -352,7 +352,7 @@ IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nullptr, sWidget, action);
SetIMEState(newState, aPresContext, nullptr, sWidget, action);
}
sWidget = nullptr;
@@ -542,7 +542,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
}
// Update IME state for new focus widget
SetIMEState(newState, aContent, newWidget, aAction);
SetIMEState(newState, aPresContext, aContent, newWidget, aAction);
}
sActiveTabParent = newTabParent;
@@ -704,7 +704,7 @@ IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
InputContextAction action(cause, InputContextAction::FOCUS_NOT_CHANGED);
IMEState newState = GetNewIMEState(aPresContext, aContent);
SetIMEState(newState, aContent, widget, action);
SetIMEState(newState, aPresContext, aContent, widget, action);
}
// static
@@ -912,7 +912,7 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
if (updateIMEState) {
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::FOCUS_NOT_CHANGED);
SetIMEState(aNewIMEState, aContent, widget, action);
SetIMEState(aNewIMEState, sPresContext, aContent, widget, action);
if (NS_WARN_IF(widget->Destroyed())) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), widget has gone during setting input context"));
@@ -1022,8 +1022,8 @@ IMEStateManager::SetInputContextForChildProcess(
MOZ_LOG(sISMLog, LogLevel::Info,
("SetInputContextForChildProcess(aTabParent=0x%p, "
"aInputContext={ mIMEState={ mEnabled=%s, mOpen=%s }, "
"mHTMLInputType=\"%s\", mHTMLInputInputmode=\"%s\", mActionHint=\"%s\" }, "
"aAction={ mCause=%s, mAction=%s }), "
"mHTMLInputType=\"%s\", mHTMLInputInputmode=\"%s\", mActionHint=\"%s\", "
"mInPrivateBrowsing=%s }, aAction={ mCause=%s, mAction=%s }), "
"sPresContext=0x%p (available: %s), sWidget=0x%p (available: %s), "
"sActiveTabParent=0x%p",
aTabParent, GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
@@ -1031,6 +1031,7 @@ IMEStateManager::SetInputContextForChildProcess(
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputType).get(),
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputInputmode).get(),
NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
GetBoolName(aInputContext.mInPrivateBrowsing),
GetActionCauseName(aAction.mCause),
GetActionFocusChangeName(aAction.mFocusChange),
sPresContext.get(), GetBoolName(CanHandleWith(sPresContext)),
@@ -1070,6 +1071,7 @@ IMEStateManager::SetInputContextForChildProcess(
// static
void
IMEStateManager::SetIMEState(const IMEState& aState,
nsPresContext* aPresContext,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction)
@@ -1090,6 +1092,10 @@ IMEStateManager::SetIMEState(const IMEState& aState,
context.mIMEState = aState;
context.mMayBeIMEUnaware = context.mIMEState.IsEditable() &&
sCheckForIMEUnawareWebApps && MayBeIMEUnawareWebApp(aContent);
context.mInPrivateBrowsing =
aPresContext &&
nsContentUtils::IsInPrivateBrowsing(aPresContext->Document());
if (aContent &&
aContent->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
@@ -1175,7 +1181,8 @@ IMEStateManager::SetInputContext(nsIWidget* aWidget,
MOZ_LOG(sISMLog, LogLevel::Info,
("SetInputContext(aWidget=0x%p, aInputContext={ "
"mIMEState={ mEnabled=%s, mOpen=%s }, mHTMLInputType=\"%s\", "
"mHTMLInputInputmode=\"%s\", mActionHint=\"%s\" }, "
"mHTMLInputInputmode=\"%s\", mActionHint=\"%s\", "
"mInPrivateBrowsing=%s }, "
"aAction={ mCause=%s, mAction=%s }), sActiveTabParent=0x%p",
aWidget,
GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
@@ -1183,6 +1190,7 @@ IMEStateManager::SetInputContext(nsIWidget* aWidget,
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputType).get(),
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputInputmode).get(),
NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
GetBoolName(aInputContext.mInPrivateBrowsing),
GetActionCauseName(aAction.mCause),
GetActionFocusChangeName(aAction.mFocusChange),
sActiveTabParent.get()));
+1
View File
@@ -247,6 +247,7 @@ protected:
nsIContent* aContent,
InputContextAction aAction);
static void SetIMEState(const IMEState &aState,
nsPresContext* aPresContext,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction);
+4 -1
View File
@@ -530,8 +530,11 @@ nsHttpNegotiateAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChanne
challenge++;
len = strlen(challenge);
if (!len)
return NS_ERROR_UNEXPECTED;
// strip off any padding (see bug 230351)
while (challenge[len - 1] == '=')
while (len && challenge[len - 1] == '=')
len--;
//
+7 -7
View File
@@ -274,6 +274,12 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T>
T* unsafeGet() { return &ptr; }
void set(const T& newPtr) {
T tmp = ptr;
ptr = newPtr;
post(tmp, ptr);
}
explicit operator bool() const {
return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
}
@@ -287,12 +293,6 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T>
post(GCPolicy<T>::initial(), ptr);
}
void set(const T& newPtr) {
T tmp = ptr;
ptr = newPtr;
post(tmp, ptr);
}
void post(const T& prev, const T& next) {
js::BarrierMethods<T>::postBarrier(&ptr, prev, next);
}
@@ -1172,13 +1172,13 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
return ptr;
}
private:
template <typename U>
void set(U&& value) {
MOZ_ASSERT(initialized());
ptr = mozilla::Forward<U>(value);
}
private:
// See the comment above Rooted::ptr.
using MaybeWrapped = typename mozilla::Conditional<
MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
+32 -59
View File
@@ -399,25 +399,21 @@ class MOZ_NON_PARAM alignas(8) Value
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
}
bool setNumber(uint32_t ui) {
void setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
setDouble((double)ui);
return false;
} else {
setInt32((int32_t)ui);
return true;
}
}
bool setNumber(double d) {
void setNumber(double d) {
int32_t i;
if (mozilla::NumberIsInt32(d, &i)) {
setInt32(i);
return true;
} else {
setDouble(d);
}
setDouble(d);
return false;
}
void setObjectOrNull(JSObject* arg) {
@@ -1406,25 +1402,29 @@ class ValueOperations
template <class Outer>
class MutableValueOperations : public ValueOperations<Outer>
{
JS::Value& value() { return static_cast<Outer*>(this)->get(); }
protected:
void set(const JS::Value& v) {
// Call Outer::set to trigger any barriers.
static_cast<Outer*>(this)->set(v);
}
public:
void setNull() { value().setNull(); }
void setUndefined() { value().setUndefined(); }
void setInt32(int32_t i) { value().setInt32(i); }
void setDouble(double d) { value().setDouble(d); }
void setNull() { set(JS::NullValue()); }
void setUndefined() { set(JS::UndefinedValue()); }
void setInt32(int32_t i) { set(JS::Int32Value(i)); }
void setDouble(double d) { set(JS::DoubleValue(d)); }
void setNaN() { setDouble(JS::GenericNaN()); }
void setBoolean(bool b) { value().setBoolean(b); }
void setMagic(JSWhyMagic why) { value().setMagic(why); }
bool setNumber(uint32_t ui) { return value().setNumber(ui); }
bool setNumber(double d) { return value().setNumber(d); }
void setString(JSString* str) { this->value().setString(str); }
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
void setPrivate(void* ptr) { this->value().setPrivate(ptr); }
void setPrivateUint32(uint32_t ui) { this->value().setPrivateUint32(ui); }
void setPrivateGCThing(js::gc::Cell* cell) { this->value().setPrivateGCThing(cell); }
void setBoolean(bool b) { set(JS::BooleanValue(b)); }
void setMagic(JSWhyMagic why) { set(JS::MagicValue(why)); }
void setNumber(uint32_t ui) { set(JS::NumberValue(ui)); }
void setNumber(double d) { set(JS::NumberValue(d)); }
void setString(JSString* str) { set(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { set(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { set(JS::ObjectValue(obj)); }
void setObjectOrNull(JSObject* arg) { set(JS::ObjectOrNullValue(arg)); }
void setPrivate(void* ptr) { set(JS::PrivateValue(ptr)); }
void setPrivateUint32(uint32_t ui) { set(JS::PrivateUint32Value(ui)); }
void setPrivateGCThing(js::gc::Cell* cell) { set(JS::PrivateGCThingValue(cell)); }
};
/*
@@ -1432,55 +1432,28 @@ class MutableValueOperations : public ValueOperations<Outer>
* type-querying, value-extracting, and mutating operations.
*/
template <>
class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
class HeapBase<JS::Value> : public MutableValueOperations<JS::Heap<JS::Value> >
{
typedef JS::Heap<JS::Value> Outer;
friend class ValueOperations<Outer>;
void setBarriered(const JS::Value& v) {
*static_cast<JS::Heap<JS::Value>*>(this) = v;
}
public:
void setNull() { setBarriered(JS::NullValue()); }
void setUndefined() { setBarriered(JS::UndefinedValue()); }
void setInt32(int32_t i) { setBarriered(JS::Int32Value(i)); }
void setDouble(double d) { setBarriered(JS::DoubleValue(d)); }
void setNaN() { setDouble(JS::GenericNaN()); }
void setBoolean(bool b) { setBarriered(JS::BooleanValue(b)); }
void setMagic(JSWhyMagic why) { setBarriered(JS::MagicValue(why)); }
void setString(JSString* str) { setBarriered(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { setBarriered(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { setBarriered(JS::ObjectValue(obj)); }
void setPrivateGCThing(js::gc::Cell* cell) { setBarriered(JS::PrivateGCThingValue(cell)); }
bool setNumber(uint32_t ui) {
void setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
setDouble((double)ui);
return false;
this->setDouble((double)ui);
} else {
setInt32((int32_t)ui);
return true;
this->setInt32((int32_t)ui);
}
}
bool setNumber(double d) {
void setNumber(double d) {
int32_t i;
if (mozilla::NumberIsInt32(d, &i)) {
setInt32(i);
return true;
this->setInt32(i);
} else {
this->setDouble(d);
}
setDouble(d);
return false;
}
void setObjectOrNull(JSObject* arg) {
if (arg)
setObject(*arg);
else
setNull();
}
};
+2 -2
View File
@@ -86,8 +86,6 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_SetInitializedLength:
case MDefinition::Op_ArrayLength:
case MDefinition::Op_SetArrayLength:
case MDefinition::Op_StoreElementHole:
case MDefinition::Op_FallibleStoreElement:
case MDefinition::Op_TypedObjectDescr:
case MDefinition::Op_Slots:
case MDefinition::Op_Elements:
@@ -143,6 +141,8 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_WasmStoreGlobalVar:
case MDefinition::Op_ArrayJoin:
case MDefinition::Op_ArraySlice:
case MDefinition::Op_StoreElementHole:
case MDefinition::Op_FallibleStoreElement:
return nullptr;
default:
#ifdef DEBUG
-9
View File
@@ -9460,12 +9460,6 @@ class MStoreElementHole
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
AliasSet getAliasSet() const override {
// StoreElementHole can update the initialized length, the array length
// or reallocate obj->elements.
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
ALLOW_CLONE(MStoreElementHole)
};
@@ -9496,9 +9490,6 @@ class MFallibleStoreElement
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
AliasSet getAliasSet() const override {
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
bool strict() const {
return strict_;
}
+21 -5
View File
@@ -35,20 +35,36 @@ interface nsIMsgAsyncPrompter : nsISupports {
in nsIMsgAsyncPromptListener aCaller);
};
[scriptable, function, uuid(acca94c9-378e-46e3-9a91-6655bf9c91a3)]
interface nsIMsgAsyncPromptCallback : nsISupports {
/**
* Called when an auth result is available. Can be passed as a function.
*
* @param aResult True if there is auth information available following the
* prompt, false otherwise.
*/
void onAuthResult(in boolean aResult);
};
/**
* This is used in combination with nsIMsgAsyncPrompter.
*/
[scriptable, uuid(fb5307a3-39d0-462e-92c8-c5c288a2612f)]
interface nsIMsgAsyncPromptListener : nsISupports {
/**
* Called when the listener should do its prompt. The listener
* should not return until the prompt is complete.
*
* @return True if there is auth information available following the prompt,
* false otherwise.
* This method has been deprecated, please use onPromptStartAsync instead.
*/
boolean onPromptStart();
/**
* Called when the listener should do its prompt. This can happen
* synchronously or asynchronously, but in any case when done the callback
* method should be called.
*
* @param aCallback The callback to execute when auth prompt has completed.
*/
void onPromptStartAsync(in nsIMsgAsyncPromptCallback aCallback);
/**
* Called in the case that the queued prompt was combined with another and
* there is now authentication information available.
+26 -7
View File
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/Deprecated.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -19,28 +20,46 @@ runnablePrompter.prototype = {
_asyncPrompter: null,
_hashKey: null,
_promiseAuthPrompt: function(listener) {
return new Promise((resolve, reject) => {
try {
listener.onPromptStartAsync({ onAuthResult: resolve });
} catch (e) {
if (e.result == Components.results.NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
// Fall back to onPromptStart, for add-ons compat
Deprecated.warning("onPromptStart has been replaced by onPromptStartAsync",
"https://bugzilla.mozilla.org/show_bug.cgi?id=1176399");
let ok = listener.onPromptStart();
resolve(ok);
} else {
reject(e);
}
}
});
},
run: Task.async(function *() {
yield Services.logins.initializationPromise;
this._asyncPrompter._log.debug("Running prompt for " + this._hashKey);
let prompter = this._asyncPrompter._pendingPrompts[this._hashKey];
let ok = false;
try {
ok = prompter.first.onPromptStart();
}
catch (ex) {
ok = yield this._promiseAuthPrompt(prompter.first);
} catch (ex) {
Components.utils.reportError("runnablePrompter:run: " + ex + "\n");
prompter.first.onPromptCanceled();
}
delete this._asyncPrompter._pendingPrompts[this._hashKey];
for (var consumer of prompter.consumers) {
try {
if (ok)
if (ok) {
consumer.onPromptAuthAvailable();
else
} else {
consumer.onPromptCanceled();
}
catch (ex) {
}
} catch (ex) {
// Log the error for extension devs and others to pick up.
Components.utils.reportError("runnablePrompter:run: consumer.onPrompt* reported an exception: " + ex + "\n");
}
+33 -9
View File
@@ -126,19 +126,43 @@ OAuth2Module.prototype = {
}
}
// Otherwise, we need a new login, so create one and fill it in.
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Ci.nsILoginInfo);
login.init(this._loginUrl, null, this._scope, this._username, token,
'', '');
loginMgr.addLogin(login);
// Unless the token is null, we need to create and fill in a new login
if (token) {
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Ci.nsILoginInfo);
login.init(this._loginUrl, null, this._scope, this._username, token,
'', '');
loginMgr.addLogin(login);
}
return token;
},
connect(aWithUI, aListener) {
this._oauth.connect(() => aListener.onSuccess(this._oauth.accessToken),
x => aListener.onFailure(x),
aWithUI, false);
let oauth = this._oauth;
let promptlistener = {
onPromptStartAsync: function(callback) {
oauth.connect(() => {
this.onPromptAuthAvailable();
callback.onAuthResult(true);
}, (err) => {
this.onPromptCanceled();
callback.onAuthResult(false);
}, aWithUI, false);
},
onPromptAuthAvailable: function() {
aListener.onSuccess(oauth.accessToken);
},
onPromptCanceled: function() {
aListener.onFailure(Components.results.NS_ERROR_ABORT);
},
onPromptStart: function() {}
};
let asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
.getService(Components.interfaces.nsIMsgAsyncPrompter);
let promptkey = this._loginUrl + "/" + this._username;
asyncprompter.queueAsyncAuthPrompt(promptkey, false, promptlistener);
},
buildXOAuth2String() {
+101 -70
View File
@@ -3,30 +3,37 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Provides OAuth 2.0 authentication
* Provides OAuth 2.0 authentication.
* @see RFC 6749
*/
var EXPORTED_SYMBOLS = ["OAuth2"];
var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/Http.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/gloda/log4moz.js");
function parseURLData(aData) {
let result = {};
aData.split(/[?#]/, 2)[1].split("&").forEach(function (aParam) {
let [key, value] = aParam.split("=");
result[key] = decodeURIComponent(value);
});
return result;
}
Cu.importGlobalProperties(["fetch"]);
// Only allow one connecting window per endpoint.
var gConnecting = {};
function OAuth2(aBaseURI, aScope, aAppKey, aAppSecret) {
/**
* Constructor for the OAuth2 object.
*
* @constructor
* @param {string} aBaseURI - The base URI for authentication and token
* requests, oauth2/auth or oauth2/token will be added for the actual
* requests.
* @param {?string} aScope - The scope as specified by RFC 6749 Section 3.3.
* Will not be included in the requests if falsy.
* @param {string} aAppKey - The client_id as specified by RFC 6749 Section
* 2.3.1.
* @param {string} [aAppSecret=null] - The client_secret as specified in
* RFC 6749 section 2.3.1. Will not be included in the requests if null.
*/
function OAuth2(aBaseURI, aScope, aAppKey, aAppSecret = null) {
this.authURI = aBaseURI + "oauth2/auth";
this.tokenURI = aBaseURI + "oauth2/token";
this.consumerKey = aAppKey;
@@ -37,12 +44,7 @@ function OAuth2(aBaseURI, aScope, aAppKey, aAppSecret) {
this.log = Log4Moz.getConfiguredLogger("TBOAuth");
}
OAuth2.CODE_AUTHORIZATION = "authorization_code";
OAuth2.CODE_REFRESH = "refresh_token";
OAuth2.prototype = {
responseType: "code",
consumerKey: null,
consumerSecret: null,
completionURI: "http://localhost",
@@ -63,7 +65,7 @@ OAuth2.prototype = {
if (!aRefresh && this.accessToken) {
aSuccess();
} else if (this.refreshToken) {
this.requestAccessToken(this.refreshToken, OAuth2.CODE_REFRESH);
this.requestAccessToken(this.refreshToken, true);
} else {
if (!aWithUI) {
aFailure('{ "error": "auth_noui" }');
@@ -78,25 +80,31 @@ OAuth2.prototype = {
},
requestAuthorization: function requestAuthorization() {
let params = [
["response_type", this.responseType],
["client_id", this.consumerKey],
["redirect_uri", this.completionURI],
];
// The scope can be optional.
let params = new URLSearchParams({
response_type: "code",
client_id: this.consumerKey,
redirect_uri: this.completionURI,
});
// The scope is optional.
if (this.scope) {
params.push(["scope", this.scope]);
params.append("scope", this.scope);
}
// Add extra parameters
params.push(...this.extraAuthParams);
for (let [name, value] of this.extraAuthParams) {
params.append(name, value);
}
// Now map the parameters to a string
params = params.map(([k,v]) => k + "=" + encodeURIComponent(v)).join("&");
let authEndpointURI = this.authURI + "?" + params.toString();
this.log.info(
"Interacting with the resource owner to obtain an authorization grant " +
"from the authorization endpoint: " +
authEndpointURI
);
this._browserRequest = {
account: this,
url: this.authURI + "?" + params,
url: authEndpointURI,
_active: true,
iconURI: "",
cancelled: function() {
@@ -170,65 +178,88 @@ OAuth2.prototype = {
delete this._browserRequest;
},
onAuthorizationReceived: function(aData) {
this.log.info("authorization received" + aData);
let results = parseURLData(aData);
if (this.responseType == "code" && results.code) {
this.requestAccessToken(results.code, OAuth2.CODE_AUTHORIZATION);
} else if (this.responseType == "token") {
this.onAccessTokenReceived(JSON.stringify(results));
// @see RFC 6749 section 4.1.2: Authorization Response
onAuthorizationReceived(aURL) {
this.log.info("OAuth2 authorization received: url=" + aURL);
let params = new URLSearchParams(aURL.split("?", 2)[1]);
if (params.has("code")) {
this.requestAccessToken(params.get("code"), false);
} else {
this.onAuthorizationFailed(null, aURL);
}
else
this.onAuthorizationFailed(null, aData);
},
onAuthorizationFailed: function(aError, aData) {
this.connectFailureCallback(aData);
},
requestAccessToken: function requestAccessToken(aCode, aType) {
let params = [
["client_id", this.consumerKey],
["client_secret", this.consumerSecret],
["grant_type", aType],
];
/**
* Request a new access token, or refresh an existing one.
* @param {string} aCode - The token issued to the client.
* @param {boolean} aRefresh - Whether it's a refresh of a token or not.
*/
requestAccessToken(aCode, aRefresh) {
// @see RFC 6749 section 4.1.3. Access Token Request
// @see RFC 6749 section 6. Refreshing an Access Token
if (aType == OAuth2.CODE_AUTHORIZATION) {
params.push(["code", aCode]);
params.push(["redirect_uri", this.completionURI]);
} else if (aType == OAuth2.CODE_REFRESH) {
params.push(["refresh_token", aCode]);
let data = new URLSearchParams();
data.append("client_id", this.consumerKey);
if (this.consumerSecret !== null) {
// Section 2.3.1. of RFC 6749 states that empty secrets MAY be omitted
// by the client. This OAuth implementation delegates this decission to
// the caller: If the secret is null, it will be omitted.
data.append("client_secret", this.consumerSecret);
}
if (aRefresh) {
this.log.info(
`Making a refresh request to the token endpoint: ${this.tokenURI}`
);
data.append("grant_type", "refresh_token");
data.append("refresh_token", aCode);
} else {
this.log.info(
`Making access token request to the token endpoint: ${this.tokenURI}`
);
data.append("grant_type", "authorization_code");
data.append("code", aCode);
data.append("redirect_uri", this.completionURI);
}
let options = {
postData: params,
onLoad: this.onAccessTokenReceived.bind(this),
onError: this.onAccessTokenFailed.bind(this)
fetch(this.tokenURI, {
method: "POST",
cache: "no-cache",
body: data,
})
.then(response => response.json())
.then(result => {
if ("error" in result) {
// RFC 6749 section 5.2. Error Response
this.log.info(
`The authorization server returned an error response: ${JSON.stringify(
result
)}`
);
this.connectFailureCallback(result);
return;
}
httpRequest(this.tokenURI, options);
},
onAccessTokenFailed: function onAccessTokenFailed(aError, aData) {
if (aError != "offline") {
this.refreshToken = null;
}
this.connectFailureCallback(aData);
},
onAccessTokenReceived: function onRequestTokenReceived(aData) {
let result = JSON.parse(aData);
// RFC 6749 section 5.1. Successful Response
this.log.info("The authorization server issued an access token.");
this.accessToken = result.access_token;
if ("refresh_token" in result) {
this.refreshToken = result.refresh_token;
this.refreshToken = result.refresh_token;
}
if ("expires_in" in result) {
this.tokenExpires = (new Date()).getTime() + (result.expires_in * 1000);
this.tokenExpires = new Date().getTime() + result.expires_in * 1000;
} else {
this.tokenExpires = Number.MAX_VALUE;
this.tokenExpires = Number.MAX_VALUE;
}
this.tokenType = result.token_type;
this.connectSuccessCallback();
})
.catch(err => {
this.log.info(`Connection to authorization server failed: ${err}`);
this.connectFailureCallback(err);
});
}
};
+40 -26
View File
@@ -5714,6 +5714,36 @@ void nsImapProtocol::ResetAuthMethods()
m_failedAuthMethods = 0;
}
nsresult nsImapProtocol::SendDataParseIMAPandCheckForNewMail(const char *aData, const char *aCommand)
{
nsresult rv;
bool isResend = false;
while (true)
{
// Send authentication string (true: suppress logging the string).
rv = SendData(aData, true);
if (NS_FAILED(rv))
break;
ParseIMAPandCheckForNewMail(aCommand);
if (!GetServerStateParser().WaitingForMoreClientInput())
break;
// The server is asking for the authentication string again. So we send
// the same string again although we know that it might be rejected again.
// We do that to get a firm authentication failure instead of a resend
// request. That keeps things in order before failing authentication and
// trying another method if capable.
if (isResend)
{
rv = NS_ERROR_FAILURE;
break;
}
isResend = true;
}
return rv;
}
nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &password, eIMAPCapabilityFlag flag)
{
ProgressEventFunctionUsingName("imapStatusSendingAuthLogin");
@@ -5880,29 +5910,7 @@ nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &passwo
PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
PR_Free(base64Str);
bool isResend = false;
while (true)
{
// Send authentication string (true: suppress logging the string).
rv = SendData(m_dataOutputBuf, true);
if (NS_FAILED(rv))
break;
ParseIMAPandCheckForNewMail(currentCommand);
if (!GetServerStateParser().WaitingForMoreClientInput())
break;
// Server is asking for authentication string again. So we send the
// same string again although we already know that it will be
// rejected again. We do that to get a firm authentication failure
// instead of a resend request. That keeps things in order before
// failing "authenticate PLAIN" and trying another method if capable.
if (isResend)
{
rv = NS_ERROR_FAILURE;
break;
}
isResend = true;
}
rv = SendDataParseIMAPandCheckForNewMail(m_dataOutputBuf, currentCommand);
} // if the last command succeeded
} // if auth plain capability
else if (flag & kHasAuthLoginCapability)
@@ -5953,9 +5961,8 @@ nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &passwo
EscapeUserNamePasswordString(password.get(), &correctedPassword);
command.Append(correctedPassword);
command.Append("\"" CRLF);
rv = SendData(command.get(), true /* suppress logging */);
NS_ENSURE_SUCCESS(rv, rv);
ParseIMAPandCheckForNewMail();
rv = SendDataParseIMAPandCheckForNewMail(command.get(), nullptr);
}
#ifdef MOZ_MAILNEWS_OAUTH2
else if (flag & kHasXOAuth2Capability)
@@ -8513,6 +8520,13 @@ nsresult nsImapProtocol::GetPassword(nsCString &password,
return rv;
}
NS_IMETHODIMP nsImapProtocol::OnPromptStartAsync(nsIMsgAsyncPromptCallback *aCallback)
{
bool result = false;
OnPromptStart(&result);
return aCallback->OnAuthResult(result);
}
// This is called from the UI thread.
NS_IMETHODIMP
nsImapProtocol::OnPromptStart(bool *aResult)
+1
View File
@@ -485,6 +485,7 @@ private:
void Namespace();
void InsecureLogin(const char *userName, const nsCString &password);
nsresult AuthLogin(const char *userName, const nsCString &password, eIMAPCapabilityFlag flag);
nsresult SendDataParseIMAPandCheckForNewMail(const char *data, const char *command);
void ProcessAuthenticatedStateURL();
void ProcessAfterAuthenticated();
void ProcessSelectedStateURL();
+7
View File
@@ -740,6 +740,13 @@ nsresult nsPop3Protocol::StartGetAsyncPassword(Pop3StatesEnum aNextState)
return rv;
}
NS_IMETHODIMP nsPop3Protocol::OnPromptStartAsync(nsIMsgAsyncPromptCallback *aCallback)
{
bool result = false;
OnPromptStart(&result);
return aCallback->OnAuthResult(result);
}
NS_IMETHODIMP nsPop3Protocol::OnPromptStart(bool *aResult)
{
MOZ_LOG(POP3LOGMODULE, LogLevel::Debug, (POP3LOG("OnPromptStart()")));
+7
View File
@@ -2472,6 +2472,13 @@ nsresult nsNNTPProtocol::PasswordResponse()
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsNNTPProtocol::OnPromptStartAsync(nsIMsgAsyncPromptCallback *aCallback)
{
bool result = false;
OnPromptStart(&result);
return aCallback->OnAuthResult(result);
}
NS_IMETHODIMP nsNNTPProtocol::OnPromptStart(bool *authAvailable)
{
NS_ENSURE_ARG_POINTER(authAvailable);
+1 -1
View File
@@ -283,9 +283,9 @@ void SoundTouch::calcEffectiveRateAndTempo()
// Sets sample rate.
void SoundTouch::setSampleRate(uint srate)
{
bSrateSet = true;
// set sample rate, leave other tempo changer parameters as they are.
pTDStretch->setParameters((int)srate);
bSrateSet = true;
}
+7 -2
View File
@@ -126,8 +126,13 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
int aSeekWindowMS, int aOverlapMS)
{
// accept only positive parameter values - if zero or negative, use old values instead
if (aSampleRate > 0) this->sampleRate = aSampleRate;
if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
if (aSampleRate > 0)
{
if (aSampleRate > 192000) ST_THROW_RT_ERROR("Error: Excessive samplerate");
this->sampleRate = aSampleRate;
}
if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
if (aSequenceMS > 0)
{
+2 -2
View File
@@ -486,8 +486,8 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
len -= 5;
// strip off any padding (see bug 230351)
while (challenge[len - 1] == '=')
len--;
while (len && challenge[len - 1] == '=')
len--;
// decode into the input secbuffer
rv = Base64Decode(challenge, len, (char**)&inBuf, &inBufLen);
@@ -8,6 +8,7 @@
#include "PSMRunnable.h"
#include "mozilla/Casting.h"
#include "mozilla/net/DNS.h"
#include "nsComponentManagerUtils.h"
#include "nsIArray.h"
#include "nsICertOverrideService.h"
@@ -681,8 +682,10 @@ GetSubjectAltNames(CERTCertificate* nssCert, nsString& allNames)
case certIPAddress:
{
char buf[INET6_ADDRSTRLEN];
// According to DNS.h, this includes space for the null-terminator
char buf[net::kNetAddrMaxCStrBufSize] = {0};
PRNetAddr addr;
memset(&addr, 0, sizeof(addr));
if (current->name.other.len == 4) {
addr.inet.family = PR_AF_INET;
memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
+3 -1
View File
@@ -11,6 +11,7 @@
#include "mozilla/NotNull.h"
#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/net/DNS.h"
#include "nsCOMPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsDateTimeFormatCID.h"
@@ -1006,8 +1007,9 @@ ProcessGeneralName(const UniquePLArenaPool& arena, CERTGeneralName* current,
break;
case certIPAddress:
{
char buf[INET6_ADDRSTRLEN];
PRStatus status = PR_FAILURE;
// According to DNS.h, this includes space for the null-terminator
char buf[net::kNetAddrMaxCStrBufSize] = {0};
PRNetAddr addr;
memset(&addr, 0, sizeof(addr));
nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
@@ -406,75 +406,107 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(const nsAFl
return mimeInfo.forget();
}
already_AddRefed<nsIMIMEInfo> nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, const nsACString& aFileExt, bool *aFound)
already_AddRefed<nsIMIMEInfo> nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
const nsACString& aFileExt,
bool *aFound)
{
*aFound = true;
*aFound = false;
const nsCString& flatType = PromiseFlatCString(aMIMEType);
const nsCString& flatExt = PromiseFlatCString(aFileExt);
nsAutoString fileExtension;
/* XXX The Equals is a gross hack to wallpaper over the most common Win32
* extension issues caused by the fix for bug 116938. See bug
* 120327, comment 271 for why this is needed. Not even sure we
CopyUTF8toUTF16(aFileExt, fileExtension);
/* XXX The octet-stream check is a gross hack to wallpaper over the most
* common Win32 extension issues caused by the fix for bug 116938. See bug
* 120327, comment 271 for why this is needed. Not even sure we
* want to remove this once we have fixed all this stuff to work
* right; any info we get from the OS on this type is pretty much
* useless....
* We'll do extension-based lookup for this type later in this function.
* useless...
*/
if (!aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM)) {
// try to use the windows mime database to see if there is a mapping to a file extension
GetExtensionFromWindowsMimeDatabase(aMIMEType, fileExtension);
LOG(("Windows mime database: extension '%s'\n", fileExtension.get()));
}
// If we found an extension for the type, do the lookup
RefPtr<nsMIMEInfoWin> mi;
if (!fileExtension.IsEmpty())
mi = GetByExtension(fileExtension, flatType.get());
LOG(("Extension lookup on '%s' found: 0x%p\n", fileExtension.get(), mi.get()));
bool haveMeaningfulMimeType =
!aMIMEType.IsEmpty() &&
!aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM);
LOG(("Extension lookup on '%s' with mimetype '%s'%s\n", fileExtension.get(),
flatType.get(),
haveMeaningfulMimeType ? " (treated as meaningful)" : ""));
bool hasDefault = false;
if (mi) {
mi->GetHasDefaultHandler(&hasDefault);
// OK. We might have the case that |aFileExt| is a valid extension for the
// mimetype we were given. In that case, we do want to append aFileExt
// to the mimeinfo that we have. (E.g.: We are asked for video/mpeg and
// .mpg, but the primary extension for video/mpeg is .mpeg. But because
// .mpg is an extension for video/mpeg content, we want to append it)
if (!aFileExt.IsEmpty() && typeFromExtEquals(NS_ConvertUTF8toUTF16(flatExt).get(), flatType.get())) {
LOG(("Appending extension '%s' to mimeinfo, because its mimetype is '%s'\n",
flatExt.get(), flatType.get()));
bool extExist = false;
mi->ExtensionExists(aFileExt, &extExist);
if (!extExist)
mi->AppendExtension(aFileExt);
}
RefPtr<nsMIMEInfoWin> mi;
// We should have *something* to go on here.
if (fileExtension.IsEmpty() && !haveMeaningfulMimeType) {
mi = new nsMIMEInfoWin(flatType.get());
return mi.forget();
}
if (!mi || !hasDefault) {
RefPtr<nsMIMEInfoWin> miByExt =
GetByExtension(NS_ConvertUTF8toUTF16(aFileExt), flatType.get());
LOG(("Ext. lookup for '%s' found 0x%p\n", flatExt.get(), miByExt.get()));
if (!miByExt && mi)
return mi.forget();
if (miByExt && !mi) {
return miByExt.forget();
}
if (!miByExt && !mi) {
*aFound = false;
mi = new nsMIMEInfoWin(flatType);
nsAutoString extensionFromMimeType;
if (haveMeaningfulMimeType) {
GetExtensionFromWindowsMimeDatabase(aMIMEType, extensionFromMimeType);
if (extensionFromMimeType.IsEmpty()) {
// We can't verify the mime type and file extension make sense.
mi = new nsMIMEInfoWin(flatType.get());
if (!aFileExt.IsEmpty()) {
mi->AppendExtension(aFileExt);
}
return mi.forget();
}
}
// Either fileExtension or extensionFromMimeType must now be non-empty.
// if we get here, mi has no default app. copy from extension lookup.
nsCOMPtr<nsIFile> defaultApp;
nsAutoString desc;
miByExt->GetDefaultDescription(desc);
*aFound = true;
mi->SetDefaultDescription(desc);
// On Windows, we prefer the file extension for lookups over the mimetype,
// because that's how windows does things.
// If we have no file extension or it doesn't match the mimetype, use the
// mime type's default file extension instead.
bool usedMimeTypeExtensionForLookup = false;
if (fileExtension.IsEmpty() ||
(haveMeaningfulMimeType &&
!typeFromExtEquals(fileExtension.get(), flatType.get()))) {
usedMimeTypeExtensionForLookup = true;
fileExtension = extensionFromMimeType;
LOG(("Now using '%s' mimetype's default file extension '%s' for lookup\n",
flatType.get(), fileExtension.get()));
}
// If we have an extension, use it for lookup:
mi = GetByExtension(fileExtension, flatType.get());
LOG(("Extension lookup on '%s' found: 0x%p\n", fileExtension.get(), mi.get()));
if (mi) {
bool hasDefault = false;
mi->GetHasDefaultHandler(&hasDefault);
// If we don't find a default handler description, see if we can find one
// using the mimetype.
if (!hasDefault && !usedMimeTypeExtensionForLookup) {
RefPtr<nsMIMEInfoWin> miFromMimeType =
GetByExtension(extensionFromMimeType, flatType.get());
LOG(("Mime-based ext. lookup for '%s' found 0x%p\n",
extensionFromMimeType.get(), miFromMimeType.get()));
if (miFromMimeType) {
nsAutoString desc;
miFromMimeType->GetDefaultDescription(desc);
mi->SetDefaultDescription(desc);
}
}
return mi.forget();
}
// The extension didn't work. Try the extension from the mimetype if
// different:
if (!extensionFromMimeType.IsEmpty() && !usedMimeTypeExtensionForLookup) {
mi = GetByExtension(extensionFromMimeType, flatType.get());
LOG(("Mime-based ext. lookup for '%s' found 0x%p\n",
extensionFromMimeType.get(), mi.get()));
}
if (mi) {
return mi.forget();
}
// This didn't work either, so just return an empty dummy mimeinfo.
*aFound = false;
mi = new nsMIMEInfoWin(flatType.get());
// If we didn't resort to the mime type's extension, we must have had a
// valid extension, so stick it on the mime info.
if (!usedMimeTypeExtensionForLookup) {
mi->AppendExtension(aFileExt);
}
return mi.forget();
}
+4
View File
@@ -300,6 +300,10 @@ struct InputContext final
* compatibility with webapps relying on key listeners. */
bool mMayBeIMEUnaware;
/* Whether the owning document of the input element has been loaded
* in private browsing mode. */
bool mInPrivateBrowsing;
bool IsOriginMainProcess() const
{
return mOrigin == ORIGIN_MAIN;
+29 -22
View File
@@ -120,24 +120,13 @@ NS_IMETHODIMP
nsClipboard::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
{
if (strcmp(aTopic, "quit-application") == 0) {
// application is going to quit, save clipboard content
Store();
// Application is going to quit, save clipboard content
gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
gdk_window_remove_filter(nullptr, selection_request_filter, nullptr);
}
return NS_OK;
}
nsresult
nsClipboard::Store(void)
{
// Ask the clipboard manager to store the current clipboard content
if (mGlobalTransferable) {
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_store(clipboard);
}
return NS_OK;
}
NS_IMETHODIMP
nsClipboard::SetData(nsITransferable *aTransferable,
nsIClipboardOwner *aOwner, int32_t aWhichClipboard)
@@ -152,9 +141,6 @@ nsClipboard::SetData(nsITransferable *aTransferable,
return NS_OK;
}
// Clear out the clipboard in order to set the new data
EmptyClipboard(aWhichClipboard);
// List of suported targets
GtkTargetList *list = gtk_target_list_new(nullptr, 0);
@@ -163,8 +149,12 @@ nsClipboard::SetData(nsITransferable *aTransferable,
nsresult rv =
aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavors));
if (!flavors || NS_FAILED(rv))
if (!flavors || NS_FAILED(rv)) {
// Clear references to the any old data and let GTK know that it is no
// longer available.
EmptyClipboard(aWhichClipboard);
return NS_ERROR_FAILURE;
}
// Add all the flavors to this widget's supported type.
bool imagesAdded = false;
@@ -232,8 +222,10 @@ nsClipboard::SetData(nsITransferable *aTransferable,
}
rv = NS_OK;
}
else {
} else {
// Clear references to the any old data and let GTK know that it is no
// longer available.
EmptyClipboard(aWhichClipboard);
rv = NS_ERROR_FAILURE;
}
@@ -373,6 +365,23 @@ nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
NS_IMETHODIMP
nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
{
if (aWhichClipboard == kSelectionClipboard) {
if (mSelectionTransferable) {
gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
MOZ_ASSERT(!mSelectionTransferable);
}
} else {
if (mGlobalTransferable) {
gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
MOZ_ASSERT(!mGlobalTransferable);
}
}
return NS_OK;
}
void
nsClipboard::ClearTransferable(int32_t aWhichClipboard) {
if (aWhichClipboard == kSelectionClipboard) {
if (mSelectionOwner) {
mSelectionOwner->LosingOwnership(mSelectionTransferable);
@@ -387,8 +396,6 @@ nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
}
mGlobalTransferable = nullptr;
}
return NS_OK;
}
NS_IMETHODIMP
@@ -652,7 +659,7 @@ nsClipboard::SelectionClearEvent(GtkClipboard *aGtkClipboard)
else
return; // THAT AIN'T NO CLIPBOARD I EVER HEARD OF
EmptyClipboard(whichClipboard);
ClearTransferable(whichClipboard);
}
void
+2 -3
View File
@@ -39,13 +39,12 @@ private:
static GdkAtom GetSelectionAtom (int32_t aWhichClipboard);
static GtkSelectionData *GetTargets (GdkAtom aWhichClipboard);
// Save global clipboard content to gtk
nsresult Store (void);
// Get our hands on the correct transferable, given a specific
// clipboard
nsITransferable *GetTransferable (int32_t aWhichClipboard);
void ClearTransferable(int32_t aWhichClipboard);
// Hang on to our owners and transferables so we can transfer data
// when asked.
nsCOMPtr<nsIClipboardOwner> mSelectionOwner;
+12 -3
View File
@@ -1355,7 +1355,9 @@ TSFTextStore::Init(nsWindowBase* aWidget,
return false;
}
SetInputScope(aContext.mHTMLInputType, aContext.mHTMLInputInputmode);
SetInputScope(aContext.mHTMLInputType,
aContext.mHTMLInputInputmode,
aContext.mInPrivateBrowsing);
// Create document manager
RefPtr<ITfThreadMgr> threadMgr = sThreadMgr;
@@ -3205,9 +3207,15 @@ TSFTextStore::InsertEmbedded(DWORD dwFlags,
void
TSFTextStore::SetInputScope(const nsString& aHTMLInputType,
const nsString& aHTMLInputInputMode)
const nsString& aHTMLInputInputMode,
bool aInPrivateBrowsing)
{
mInputScopes.Clear();
if (aInPrivateBrowsing) {
mInputScopes.AppendElement(IS_PRIVATE);
}
if (aHTMLInputType.IsEmpty() || aHTMLInputType.EqualsLiteral("text")) {
if (aHTMLInputInputMode.EqualsLiteral("url")) {
mInputScopes.AppendElement(IS_URL);
@@ -5688,7 +5696,8 @@ TSFTextStore::SetInputContext(nsWindowBase* aWidget,
if (sEnabledTextStore) {
RefPtr<TSFTextStore> textStore(sEnabledTextStore);
textStore->SetInputScope(aContext.mHTMLInputType,
aContext.mHTMLInputInputmode);
aContext.mHTMLInputInputmode,
aContext.mInPrivateBrowsing);
}
return;
}
+2 -1
View File
@@ -355,7 +355,8 @@ protected:
ULONG aFilterCount,
const TS_ATTRID* aFilterAttrs);
void SetInputScope(const nsString& aHTMLInputType,
const nsString& aHTMLInputInputmode);
const nsString& aHTMLInputInputmode,
bool aInPrivateBrowsing);
// Creates native caret over our caret. This method only works on desktop
// application. Otherwise, this does nothing.
+38 -54
View File
@@ -409,7 +409,7 @@ IMEHandler::OnDestroyWindow(nsWindow* aWindow)
if (!sIsInTSFMode) {
// MSDN says we need to set IS_DEFAULT to avoid memory leak when we use
// SetInputScopes API. Use an empty string to do this.
SetInputScopeForIMM32(aWindow, EmptyString(), EmptyString());
SetInputScopeForIMM32(aWindow, EmptyString(), EmptyString(), false);
}
#endif // #ifdef NS_ENABLE_TSF
AssociateIMEContext(aWindow, true);
@@ -481,8 +481,10 @@ IMEHandler::SetInputContext(nsWindow* aWindow,
}
} else {
// Set at least InputScope even when TextStore is not available.
SetInputScopeForIMM32(aWindow, aInputContext.mHTMLInputType,
aInputContext.mHTMLInputInputmode);
SetInputScopeForIMM32(aWindow,
aInputContext.mHTMLInputType,
aInputContext.mHTMLInputInputmode,
aInputContext.mInPrivateBrowsing);
}
#endif // #ifdef NS_ENABLE_TSF
@@ -583,82 +585,64 @@ IMEHandler::OnKeyboardLayoutChanged()
void
IMEHandler::SetInputScopeForIMM32(nsWindow* aWindow,
const nsAString& aHTMLInputType,
const nsAString& aHTMLInputInputmode)
const nsAString& aHTMLInputInputmode,
bool aInPrivateBrowsing)
{
if (sIsInTSFMode || !sSetInputScopes || aWindow->Destroyed()) {
return;
}
UINT arraySize = 0;
const InputScope* scopes = nullptr;
AutoTArray<InputScope, 3> scopes;
if (aInPrivateBrowsing) {
scopes.AppendElement(IS_PRIVATE);
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html
if (aHTMLInputType.IsEmpty() || aHTMLInputType.EqualsLiteral("text")) {
if (aHTMLInputInputmode.EqualsLiteral("url")) {
static const InputScope inputScopes[] = { IS_URL };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_URL);
} else if (aHTMLInputInputmode.EqualsLiteral("email")) {
static const InputScope inputScopes[] = { IS_EMAIL_SMTPEMAILADDRESS };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_EMAIL_SMTPEMAILADDRESS);
} else if (aHTMLInputInputmode.EqualsLiteral("tel")) {
static const InputScope inputScopes[] =
{IS_TELEPHONE_LOCALNUMBER, IS_TELEPHONE_FULLTELEPHONENUMBER};
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_TELEPHONE_LOCALNUMBER);
scopes.AppendElement(IS_TELEPHONE_FULLTELEPHONENUMBER);
} else if (aHTMLInputInputmode.EqualsLiteral("numeric")) {
static const InputScope inputScopes[] = { IS_NUMBER };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_NUMBER);
} else {
static const InputScope inputScopes[] = { IS_DEFAULT };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_DEFAULT);
}
} else if (aHTMLInputType.EqualsLiteral("url")) {
static const InputScope inputScopes[] = { IS_URL };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_URL);
} else if (aHTMLInputType.EqualsLiteral("search")) {
static const InputScope inputScopes[] = { IS_SEARCH };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_SEARCH);
} else if (aHTMLInputType.EqualsLiteral("email")) {
static const InputScope inputScopes[] = { IS_EMAIL_SMTPEMAILADDRESS };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_EMAIL_SMTPEMAILADDRESS);
} else if (aHTMLInputType.EqualsLiteral("password")) {
static const InputScope inputScopes[] = { IS_PASSWORD };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_PASSWORD);
} else if (aHTMLInputType.EqualsLiteral("datetime") ||
aHTMLInputType.EqualsLiteral("datetime-local")) {
static const InputScope inputScopes[] = {
IS_DATE_FULLDATE, IS_TIME_FULLTIME };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_DATE_FULLDATE);
scopes.AppendElement(IS_TIME_FULLTIME);
} else if (aHTMLInputType.EqualsLiteral("date") ||
aHTMLInputType.EqualsLiteral("month") ||
aHTMLInputType.EqualsLiteral("week")) {
static const InputScope inputScopes[] = { IS_DATE_FULLDATE };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_DATE_FULLDATE);
} else if (aHTMLInputType.EqualsLiteral("time")) {
static const InputScope inputScopes[] = { IS_TIME_FULLTIME };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_TIME_FULLTIME);
} else if (aHTMLInputType.EqualsLiteral("tel")) {
static const InputScope inputScopes[] = {
IS_TELEPHONE_FULLTELEPHONENUMBER, IS_TELEPHONE_LOCALNUMBER };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_TELEPHONE_FULLTELEPHONENUMBER);
scopes.AppendElement(IS_TELEPHONE_LOCALNUMBER);
} else if (aHTMLInputType.EqualsLiteral("number")) {
static const InputScope inputScopes[] = { IS_NUMBER };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_NUMBER);
}
if (scopes && arraySize > 0) {
sSetInputScopes(aWindow->GetWindowHandle(), scopes, arraySize, nullptr, 0,
nullptr, nullptr);
if (!scopes.IsEmpty()) {
sSetInputScopes(aWindow->GetWindowHandle(),
scopes.Elements(),
scopes.Length(),
nullptr,
0,
nullptr,
nullptr);
}
}
+2 -1
View File
@@ -144,7 +144,8 @@ private:
static decltype(SetInputScopes)* sSetInputScopes;
static void SetInputScopeForIMM32(nsWindow* aWindow,
const nsAString& aHTMLInputType,
const nsAString& aHTMLInputInputmode);
const nsAString& aHTMLInputInputmode,
bool aInPrivateBrowsing);
static bool sIsInTSFMode;
// If sIMMEnabled is false, any IME messages are not handled in TSF mode.
// Additionally, IME context is always disassociated from focused window.