Skip to content
This repository has been archived by the owner on Nov 7, 2018. It is now read-only.

Commit

Permalink
Bug 1496242 - Part II, Convert datetimebox to UA Widget r=dholbert,ja…
Browse files Browse the repository at this point in the history
…ws,smaug

This patch converts datetimebox.xml to datetimebox.js and loads it as a UA Widget,
while touches things here and there to make it work.

In HTMLInputElement manages the lifecycle of the datetimebox UA Widget.
It is loaded when in <input> has type date or time, or have its type switch to date or time.

nsDateTimeControlFrame is changed so that when UA Widget is enabled,
it would not generate <xul:datetimebox>.

Like bug 1483972, a check is added in nsCSSFrameConstructor::CreateGeneratedContentItem()
to make sure we don't generate pseudo content inside <input>.

Assertions in IntlUtils is changed to allow UAWidget to call the methods.

Depends on D9056

Differential Revision: https://phabricator.services.mozilla.com/D9057
  • Loading branch information
timdream committed Nov 3, 2018
1 parent 5f6d151 commit cbf48a7
Show file tree
Hide file tree
Showing 16 changed files with 1,947 additions and 59 deletions.
6 changes: 4 additions & 2 deletions dom/base/IntlUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ IntlUtils::GetDisplayNames(const Sequence<nsString>& aLocales,
DisplayNameResult& aResult, ErrorResult& aError)
{
MOZ_ASSERT(nsContentUtils::IsCallerChrome() ||
nsContentUtils::IsCallerContentXBL());
nsContentUtils::IsCallerContentXBL() ||
nsContentUtils::IsCallerUAWidget());

nsCOMPtr<mozIMozIntl> mozIntl = do_GetService("@mozilla.org/mozintl;1");
if (!mozIntl) {
Expand Down Expand Up @@ -98,7 +99,8 @@ IntlUtils::GetLocaleInfo(const Sequence<nsString>& aLocales,
LocaleInfo& aResult, ErrorResult& aError)
{
MOZ_ASSERT(nsContentUtils::IsCallerChrome() ||
nsContentUtils::IsCallerContentXBL());
nsContentUtils::IsCallerContentXBL() ||
nsContentUtils::IsCallerUAWidget());

nsCOMPtr<mozIMozIntl> mozIntl = do_GetService("@mozilla.org/mozintl;1");
if (!mozIntl) {
Expand Down
16 changes: 16 additions & 0 deletions dom/base/nsContentUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2344,6 +2344,22 @@ nsContentUtils::IsCallerContentXBL()
return xpc::IsContentXBLScope(realm);
}

bool
nsContentUtils::IsCallerUAWidget()
{
JSContext *cx = GetCurrentJSContext();
if (!cx) {
return false;
}

JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
if (!realm) {
return false;
}

return xpc::IsUAWidgetScope(realm);
}

bool
nsContentUtils::IsSystemCaller(JSContext* aCx)
{
Expand Down
1 change: 1 addition & 0 deletions dom/base/nsContentUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class nsContentUtils
static bool IsCallerChrome();
static bool ThreadsafeIsCallerChrome();
static bool IsCallerContentXBL();
static bool IsCallerUAWidget();
static bool IsFuzzingEnabled()
#ifndef FUZZING
{
Expand Down
65 changes: 64 additions & 1 deletion dom/html/HTMLInputElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2223,7 +2223,7 @@ void HTMLInputElement::GetDateTimeInputBoxValue(DateTimeValue& aValue)
Element* HTMLInputElement::GetDateTimeBoxElement()
{
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
if (frame && frame->GetInputAreaContent()) {
return frame->GetInputAreaContent()->AsElement();
}
return nullptr;
Expand Down Expand Up @@ -4643,6 +4643,19 @@ HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
// And now make sure our state is up to date
UpdateState(false);

if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
nsContentUtils::IsUAWidgetEnabled() &&
IsInComposedDoc()) {
// Construct Shadow Root so web content can be hidden in the DOM.
AttachAndSetUAShadowRoot();
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("UAWidgetBindToTree"),
CanBubble::eYes,
ChromeOnlyDispatch::eYes);
dispatcher->RunDOMEventWhenSafe();
}

if (mType == NS_FORM_INPUT_PASSWORD) {
if (IsInComposedDoc()) {
AsyncEventDispatcher* dispatcher =
Expand Down Expand Up @@ -4684,6 +4697,20 @@ HTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent)

// And now make sure our state is up to date
UpdateState(false);

if (GetShadowRoot() && IsInComposedDoc()) {
RefPtr<Element> self = this;
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
"HTMLInputElement::UnbindFromTree::UAWidgetUnbindFromTree",
[self]() {
nsContentUtils::DispatchChromeEvent(
self->OwnerDoc(), self,
NS_LITERAL_STRING("UAWidgetUnbindFromTree"),
CanBubble::eYes, Cancelable::eNo);
self->UnattachShadow();
})
);
}
}

void
Expand Down Expand Up @@ -4849,6 +4876,42 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify)
ChromeOnlyDispatch::eYes);
dispatcher->PostDOMEvent();
}

if (nsContentUtils::IsUAWidgetEnabled() && IsInComposedDoc()) {
if (oldType == NS_FORM_INPUT_TIME || oldType == NS_FORM_INPUT_DATE) {
if (mType != NS_FORM_INPUT_TIME && mType != NS_FORM_INPUT_DATE) {
// Switch away from date/time type.
RefPtr<Element> self = this;
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
"HTMLInputElement::UnbindFromTree::UAWidgetUnbindFromTree",
[self]() {
nsContentUtils::DispatchChromeEvent(
self->OwnerDoc(), self,
NS_LITERAL_STRING("UAWidgetUnbindFromTree"),
CanBubble::eYes, Cancelable::eNo);
self->UnattachShadow();
})
);
} else {
// Switch between date and time.
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("UAWidgetAttributeChanged"),
CanBubble::eYes,
ChromeOnlyDispatch::eYes);
dispatcher->RunDOMEventWhenSafe();
}
} else if (mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) {
// Switch to date/time type.
AttachAndSetUAShadowRoot();
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("UAWidgetBindToTree"),
CanBubble::eYes,
ChromeOnlyDispatch::eYes);
dispatcher->RunDOMEventWhenSafe();
}
}
}

void
Expand Down
16 changes: 8 additions & 8 deletions dom/webidl/HTMLInputElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ interface MozEditableElement {
// This is similar to set .value on nsIDOMInput/TextAreaElements, but handling
// of the value change is closer to the normal user input, so 'change' event
// for example will be dispatched when focusing out the element.
[Func="IsChromeOrXBL", NeedsSubjectPrincipal]
[Func="IsChromeOrXBLOrUAWidget", NeedsSubjectPrincipal]
void setUserInput(DOMString input);
};

Expand Down Expand Up @@ -252,26 +252,26 @@ partial interface HTMLInputElement {
BinaryName="getMaximumAsDouble"]
double getMaximum();

[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget"]
void openDateTimePicker(optional DateTimeValue initialValue);

[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget"]
void updateDateTimePicker(optional DateTimeValue value);

[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget"]
void closeDateTimePicker();

[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget"]
void setFocusState(boolean aIsFocused);

[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget"]
void updateValidityState();

[Pref="dom.forms.datetime", Func="IsChromeOrXBL",
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget",
BinaryName="getStepAsDouble"]
double getStep();

[Pref="dom.forms.datetime", Func="IsChromeOrXBL",
[Pref="dom.forms.datetime", Func="IsChromeOrXBLOrUAWidget",
BinaryName="getStepBaseAsDouble"]
double getStepBase();
};
Expand Down
4 changes: 2 additions & 2 deletions dom/webidl/Window.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -560,14 +560,14 @@ partial interface Window {
*
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
*/
[Func="IsChromeOrXBL"]
[Func="IsChromeOrXBLOrUAWidget"]
sequence<DOMString> getRegionalPrefsLocales();

/**
* Getter funcion for IntlUtils, which provides helper functions for
* localization.
*/
[Throws, Func="IsChromeOrXBL"]
[Throws, Func="IsChromeOrXBLOrUAWidget"]
readonly attribute IntlUtils intlUtils;
};

Expand Down
6 changes: 4 additions & 2 deletions layout/base/nsCSSFrameConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1795,8 +1795,10 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat
aPseudoElement == CSSPseudoElementType::after,
"unexpected aPseudoElement");

if (aParentFrame && aParentFrame->IsHTMLVideoFrame()) {
// Video frames may not be leafs when backed by an UA widget, but we still don't want to expose generated content.
if (aParentFrame &&
(aParentFrame->IsHTMLVideoFrame() || aParentFrame->IsDateTimeControlFrame())) {
// Video frames and date time control frames may not be leafs when backed by an UA widget,
// but we still don't want to expose generated content.
MOZ_ASSERT(aOriginatingElement.GetShadowRoot()->IsUAWidget());
return;
}
Expand Down
Loading

0 comments on commit cbf48a7

Please sign in to comment.