Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsDOMWindowUtils.h"
8 #include "mozilla/layers/CompositorChild.h"
9 #include "mozilla/layers/LayerTransactionChild.h"
10 #include "nsPresContext.h"
11 #include "nsDOMClassInfoID.h"
12 #include "nsError.h"
13 #include "nsIDOMEvent.h"
14 #include "nsQueryContentEventResult.h"
15 #include "CompositionStringSynthesizer.h"
16 #include "nsGlobalWindow.h"
17 #include "nsIDocument.h"
18 #include "nsFocusManager.h"
19 #include "nsFrameManager.h"
20 #include "nsRefreshDriver.h"
21 #include "mozilla/dom/Touch.h"
22 #include "nsIObjectLoadingContent.h"
23 #include "nsFrame.h"
24 #include "mozilla/layers/ShadowLayers.h"
26 #include "nsIScrollableFrame.h"
28 #include "nsContentUtils.h"
30 #include "nsIFrame.h"
31 #include "nsIWidget.h"
32 #include "nsCharsetSource.h"
33 #include "nsJSEnvironment.h"
34 #include "nsJSUtils.h"
36 #include "mozilla/EventStateManager.h"
37 #include "mozilla/MiscEvents.h"
38 #include "mozilla/MouseEvents.h"
39 #include "mozilla/TextEvents.h"
40 #include "mozilla/TouchEvents.h"
42 #include "nsViewManager.h"
44 #include "nsIDOMHTMLCanvasElement.h"
45 #include "nsLayoutUtils.h"
46 #include "nsComputedDOMStyle.h"
47 #include "nsIPresShell.h"
48 #include "nsStyleAnimation.h"
49 #include "nsCSSProps.h"
50 #include "nsDOMFile.h"
51 #include "nsTArrayHelpers.h"
52 #include "nsIDocShell.h"
53 #include "nsIContentViewer.h"
54 #include "nsIMarkupDocumentViewer.h"
55 #include "mozilla/dom/DOMRect.h"
56 #include <algorithm>
58 #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
59 #include <gdk/gdk.h>
60 #include <gdk/gdkx.h>
61 #endif
63 #include "Layers.h"
64 #include "mozilla/layers/ShadowLayers.h"
66 #include "mozilla/dom/Element.h"
67 #include "mozilla/dom/file/FileHandle.h"
68 #include "mozilla/dom/FileHandleBinding.h"
69 #include "mozilla/dom/TabChild.h"
70 #include "mozilla/dom/IDBFactoryBinding.h"
71 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
72 #include "mozilla/dom/quota/PersistenceType.h"
73 #include "mozilla/dom/quota/QuotaManager.h"
74 #include "nsDOMBlobBuilder.h"
75 #include "nsPrintfCString.h"
76 #include "nsViewportInfo.h"
77 #include "nsIFormControl.h"
78 #include "nsIScriptError.h"
79 #include "nsIAppShell.h"
80 #include "nsWidgetsCID.h"
81 #include "FrameLayerBuilder.h"
82 #include "nsDisplayList.h"
83 #include "nsROCSSPrimitiveValue.h"
84 #include "nsIBaseWindow.h"
85 #include "nsIDocShellTreeOwner.h"
86 #include "nsIInterfaceRequestorUtils.h"
87 #include "GeckoProfiler.h"
88 #include "mozilla/Preferences.h"
89 #include "nsIContentIterator.h"
91 #ifdef XP_WIN
92 #undef GetClassName
93 #endif
95 using namespace mozilla;
96 using namespace mozilla::dom;
97 using namespace mozilla::layers;
98 using namespace mozilla::widget;
99 using namespace mozilla::gfx;
101 class gfxContext;
103 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
105 DOMCI_DATA(WindowUtils, nsDOMWindowUtils)
107 NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
108 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils)
109 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils)
110 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
111 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WindowUtils)
112 NS_INTERFACE_MAP_END
114 NS_IMPL_ADDREF(nsDOMWindowUtils)
115 NS_IMPL_RELEASE(nsDOMWindowUtils)
117 nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindow *aWindow)
118 {
119 nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
120 mWindow = do_GetWeakReference(supports);
121 NS_ASSERTION(aWindow->IsOuterWindow(), "How did that happen?");
122 }
124 nsDOMWindowUtils::~nsDOMWindowUtils()
125 {
126 }
128 nsIPresShell*
129 nsDOMWindowUtils::GetPresShell()
130 {
131 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
132 if (!window)
133 return nullptr;
135 nsIDocShell *docShell = window->GetDocShell();
136 if (!docShell)
137 return nullptr;
139 return docShell->GetPresShell();
140 }
142 nsPresContext*
143 nsDOMWindowUtils::GetPresContext()
144 {
145 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
146 if (!window)
147 return nullptr;
148 nsIDocShell *docShell = window->GetDocShell();
149 if (!docShell)
150 return nullptr;
151 nsRefPtr<nsPresContext> presContext;
152 docShell->GetPresContext(getter_AddRefs(presContext));
153 return presContext;
154 }
156 nsIDocument*
157 nsDOMWindowUtils::GetDocument()
158 {
159 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
160 if (!window) {
161 return nullptr;
162 }
163 return window->GetExtantDoc();
164 }
166 LayerTransactionChild*
167 nsDOMWindowUtils::GetLayerTransaction()
168 {
169 nsIWidget* widget = GetWidget();
170 if (!widget)
171 return nullptr;
173 LayerManager* manager = widget->GetLayerManager();
174 if (!manager)
175 return nullptr;
177 ShadowLayerForwarder* forwarder = manager->AsShadowForwarder();
178 return forwarder && forwarder->HasShadowManager() ?
179 forwarder->GetShadowManager() :
180 nullptr;
181 }
183 NS_IMETHODIMP
184 nsDOMWindowUtils::GetImageAnimationMode(uint16_t *aMode)
185 {
186 if (!nsContentUtils::IsCallerChrome()) {
187 return NS_ERROR_DOM_SECURITY_ERR;
188 }
190 NS_ENSURE_ARG_POINTER(aMode);
191 *aMode = 0;
192 nsPresContext* presContext = GetPresContext();
193 if (presContext) {
194 *aMode = presContext->ImageAnimationMode();
195 return NS_OK;
196 }
197 return NS_ERROR_NOT_AVAILABLE;
198 }
200 NS_IMETHODIMP
201 nsDOMWindowUtils::SetImageAnimationMode(uint16_t aMode)
202 {
203 if (!nsContentUtils::IsCallerChrome()) {
204 return NS_ERROR_DOM_SECURITY_ERR;
205 }
207 nsPresContext* presContext = GetPresContext();
208 if (presContext) {
209 presContext->SetImageAnimationMode(aMode);
210 return NS_OK;
211 }
212 return NS_ERROR_NOT_AVAILABLE;
213 }
215 NS_IMETHODIMP
216 nsDOMWindowUtils::GetDocCharsetIsForced(bool *aIsForced)
217 {
218 *aIsForced = false;
220 if (!nsContentUtils::IsCallerChrome()) {
221 return NS_ERROR_DOM_SECURITY_ERR;
222 }
224 nsIDocument* doc = GetDocument();
225 *aIsForced = doc &&
226 doc->GetDocumentCharacterSetSource() >= kCharsetFromParentForced;
227 return NS_OK;
228 }
230 NS_IMETHODIMP
231 nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
232 nsAString& aValue)
233 {
234 if (!nsContentUtils::IsCallerChrome()) {
235 return NS_ERROR_DOM_SECURITY_ERR;
236 }
238 nsIDocument* doc = GetDocument();
239 if (doc) {
240 nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
241 doc->GetHeaderData(name, aValue);
242 return NS_OK;
243 }
245 aValue.Truncate();
246 return NS_OK;
247 }
249 NS_IMETHODIMP
250 nsDOMWindowUtils::Redraw(uint32_t aCount, uint32_t *aDurationOut)
251 {
252 if (!nsContentUtils::IsCallerChrome()) {
253 return NS_ERROR_DOM_SECURITY_ERR;
254 }
256 if (aCount == 0)
257 aCount = 1;
259 if (nsIPresShell* presShell = GetPresShell()) {
260 nsIFrame *rootFrame = presShell->GetRootFrame();
262 if (rootFrame) {
263 PRIntervalTime iStart = PR_IntervalNow();
265 for (uint32_t i = 0; i < aCount; i++)
266 rootFrame->InvalidateFrame();
268 #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
269 XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), False);
270 #endif
272 *aDurationOut = PR_IntervalToMilliseconds(PR_IntervalNow() - iStart);
274 return NS_OK;
275 }
276 }
277 return NS_ERROR_FAILURE;
278 }
280 NS_IMETHODIMP
281 nsDOMWindowUtils::SetCSSViewport(float aWidthPx, float aHeightPx)
282 {
283 if (!nsContentUtils::IsCallerChrome()) {
284 return NS_ERROR_DOM_SECURITY_ERR;
285 }
287 if (!(aWidthPx >= 0.0 && aHeightPx >= 0.0)) {
288 return NS_ERROR_ILLEGAL_VALUE;
289 }
291 nsIPresShell* presShell = GetPresShell();
292 if (!presShell) {
293 return NS_ERROR_FAILURE;
294 }
296 nscoord width = nsPresContext::CSSPixelsToAppUnits(aWidthPx);
297 nscoord height = nsPresContext::CSSPixelsToAppUnits(aHeightPx);
299 presShell->ResizeReflowOverride(width, height);
301 return NS_OK;
302 }
304 NS_IMETHODIMP
305 nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth,
306 uint32_t aDisplayHeight,
307 double *aDefaultZoom, bool *aAllowZoom,
308 double *aMinZoom, double *aMaxZoom,
309 uint32_t *aWidth, uint32_t *aHeight,
310 bool *aAutoSize)
311 {
312 nsIDocument* doc = GetDocument();
313 NS_ENSURE_STATE(doc);
315 nsViewportInfo info = nsContentUtils::GetViewportInfo(doc, ScreenIntSize(aDisplayWidth, aDisplayHeight));
316 *aDefaultZoom = info.GetDefaultZoom().scale;
317 *aAllowZoom = info.IsZoomAllowed();
318 *aMinZoom = info.GetMinZoom().scale;
319 *aMaxZoom = info.GetMaxZoom().scale;
320 *aWidth = info.GetSize().width;
321 *aHeight = info.GetSize().height;
322 *aAutoSize = info.IsAutoSizeEnabled();
323 return NS_OK;
324 }
326 NS_IMETHODIMP
327 nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
328 float aWidthPx, float aHeightPx,
329 nsIDOMElement* aElement,
330 uint32_t aPriority)
331 {
332 if (!nsContentUtils::IsCallerChrome()) {
333 return NS_ERROR_DOM_SECURITY_ERR;
334 }
336 nsIPresShell* presShell = GetPresShell();
337 if (!presShell) {
338 return NS_ERROR_FAILURE;
339 }
341 if (!aElement) {
342 return NS_ERROR_INVALID_ARG;
343 }
345 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
347 if (!content) {
348 return NS_ERROR_INVALID_ARG;
349 }
351 if (content->GetCurrentDoc() != presShell->GetDocument()) {
352 return NS_ERROR_INVALID_ARG;
353 }
355 DisplayPortPropertyData* currentData =
356 static_cast<DisplayPortPropertyData*>(content->GetProperty(nsGkAtoms::DisplayPort));
357 if (currentData && currentData->mPriority > aPriority) {
358 return NS_OK;
359 }
361 nsRect displayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
362 nsPresContext::CSSPixelsToAppUnits(aYPx),
363 nsPresContext::CSSPixelsToAppUnits(aWidthPx),
364 nsPresContext::CSSPixelsToAppUnits(aHeightPx));
366 content->SetProperty(nsGkAtoms::DisplayPort,
367 new DisplayPortPropertyData(displayport, aPriority),
368 nsINode::DeleteProperty<DisplayPortPropertyData>);
370 nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
371 if (rootScrollFrame && content == rootScrollFrame->GetContent()) {
372 // We are setting a root displayport for a document.
373 // The pres shell needs a special flag set.
374 presShell->SetIgnoreViewportScrolling(true);
375 }
377 nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
378 if (rootFrame) {
379 rootFrame->SchedulePaint();
381 // If we are hiding something that is a display root then send empty paint
382 // transaction in order to release retained layers because it won't get
383 // any more paint requests when it is hidden.
384 if (displayport.IsEmpty() &&
385 rootFrame == nsLayoutUtils::GetDisplayRootFrame(rootFrame)) {
386 nsCOMPtr<nsIWidget> widget = GetWidget();
387 if (widget) {
388 bool isRetainingManager;
389 LayerManager* manager = widget->GetLayerManager(&isRetainingManager);
390 if (isRetainingManager) {
391 manager->BeginTransaction();
392 nsLayoutUtils::PaintFrame(nullptr, rootFrame, nsRegion(), NS_RGB(255, 255, 255),
393 nsLayoutUtils::PAINT_WIDGET_LAYERS |
394 nsLayoutUtils::PAINT_EXISTING_TRANSACTION);
395 }
396 }
397 }
398 }
400 return NS_OK;
401 }
403 NS_IMETHODIMP
404 nsDOMWindowUtils::SetDisplayPortMarginsForElement(float aLeftMargin,
405 float aTopMargin,
406 float aRightMargin,
407 float aBottomMargin,
408 uint32_t aAlignmentX,
409 uint32_t aAlignmentY,
410 nsIDOMElement* aElement,
411 uint32_t aPriority)
412 {
413 if (!nsContentUtils::IsCallerChrome()) {
414 return NS_ERROR_DOM_SECURITY_ERR;
415 }
417 nsIPresShell* presShell = GetPresShell();
418 if (!presShell) {
419 return NS_ERROR_FAILURE;
420 }
422 if (!aElement) {
423 return NS_ERROR_INVALID_ARG;
424 }
426 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
428 if (!content) {
429 return NS_ERROR_INVALID_ARG;
430 }
432 if (content->GetCurrentDoc() != presShell->GetDocument()) {
433 return NS_ERROR_INVALID_ARG;
434 }
436 // Note order change of arguments between our function signature and
437 // LayerMargin constructor.
438 LayerMargin displayportMargins(aTopMargin,
439 aRightMargin,
440 aBottomMargin,
441 aLeftMargin);
443 nsLayoutUtils::SetDisplayPortMargins(content, presShell, displayportMargins,
444 aAlignmentX, aAlignmentY, aPriority);
446 return NS_OK;
447 }
450 NS_IMETHODIMP
451 nsDOMWindowUtils::SetDisplayPortBaseForElement(int32_t aX,
452 int32_t aY,
453 int32_t aWidth,
454 int32_t aHeight,
455 nsIDOMElement* aElement)
456 {
457 if (!nsContentUtils::IsCallerChrome()) {
458 return NS_ERROR_DOM_SECURITY_ERR;
459 }
461 nsIPresShell* presShell = GetPresShell();
462 if (!presShell) {
463 return NS_ERROR_FAILURE;
464 }
466 if (!aElement) {
467 return NS_ERROR_INVALID_ARG;
468 }
470 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
472 if (!content) {
473 return NS_ERROR_INVALID_ARG;
474 }
476 if (content->GetCurrentDoc() != presShell->GetDocument()) {
477 return NS_ERROR_INVALID_ARG;
478 }
480 nsLayoutUtils::SetDisplayPortBase(content, nsRect(aX, aY, aWidth, aHeight));
482 return NS_OK;
483 }
485 NS_IMETHODIMP
486 nsDOMWindowUtils::SetCriticalDisplayPortForElement(float aXPx, float aYPx,
487 float aWidthPx, float aHeightPx,
488 nsIDOMElement* aElement)
489 {
490 if (!nsContentUtils::IsCallerChrome()) {
491 return NS_ERROR_DOM_SECURITY_ERR;
492 }
494 nsIPresShell* presShell = GetPresShell();
495 if (!presShell) {
496 return NS_ERROR_FAILURE;
497 }
499 if (!aElement) {
500 return NS_ERROR_INVALID_ARG;
501 }
503 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
505 if (!content) {
506 return NS_ERROR_INVALID_ARG;
507 }
509 if (content->GetCurrentDoc() != presShell->GetDocument()) {
510 return NS_ERROR_INVALID_ARG;
511 }
513 nsRect displayport;
514 if (!nsLayoutUtils::GetDisplayPort(content, &displayport)) {
515 return NS_ERROR_INVALID_ARG;
516 }
518 nsRect criticalDisplayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
519 nsPresContext::CSSPixelsToAppUnits(aYPx),
520 nsPresContext::CSSPixelsToAppUnits(aWidthPx),
521 nsPresContext::CSSPixelsToAppUnits(aHeightPx));
522 content->SetProperty(nsGkAtoms::CriticalDisplayPort, new nsRect(criticalDisplayport),
523 nsINode::DeleteProperty<nsRect>);
525 nsIFrame* rootFrame = presShell->GetRootFrame();
526 if (rootFrame) {
527 rootFrame->InvalidateFrame();
528 }
530 return NS_OK;
531 }
533 NS_IMETHODIMP
534 nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
535 {
536 if (!nsContentUtils::IsCallerChrome()) {
537 return NS_ERROR_DOM_SECURITY_ERR;
538 }
540 nsIPresShell* presShell = GetPresShell();
541 if (!presShell) {
542 return NS_ERROR_FAILURE;
543 }
545 nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
546 if (sf) {
547 sf->SetResolution(gfxSize(aXResolution, aYResolution));
548 presShell->SetResolution(aXResolution, aYResolution);
549 }
551 return NS_OK;
552 }
554 NS_IMETHODIMP
555 nsDOMWindowUtils::GetResolution(float* aXResolution, float* aYResolution)
556 {
557 if (!nsContentUtils::IsCallerChrome()) {
558 return NS_ERROR_DOM_SECURITY_ERR;
559 }
561 nsIPresShell* presShell = GetPresShell();
562 if (!presShell) {
563 return NS_ERROR_FAILURE;
564 }
566 nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
567 if (sf) {
568 const gfxSize& res = sf->GetResolution();
569 *aXResolution = res.width;
570 *aYResolution = res.height;
571 } else {
572 *aXResolution = presShell->GetXResolution();
573 *aYResolution = presShell->GetYResolution();
574 }
576 return NS_OK;
577 }
579 NS_IMETHODIMP
580 nsDOMWindowUtils::GetIsResolutionSet(bool* aIsResolutionSet) {
581 if (!nsContentUtils::IsCallerChrome()) {
582 return NS_ERROR_DOM_SECURITY_ERR;
583 }
585 nsIPresShell* presShell = GetPresShell();
586 if (!presShell) {
587 return NS_ERROR_FAILURE;
588 }
590 const nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
591 *aIsResolutionSet = sf && sf->IsResolutionSet();
593 return NS_OK;
594 }
596 NS_IMETHODIMP
597 nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint)
598 {
599 if (!nsContentUtils::IsCallerChrome()) {
600 return NS_ERROR_DOM_SECURITY_ERR;
601 }
603 nsIPresShell* presShell = GetPresShell();
604 if (presShell) {
605 presShell->SetIsFirstPaint(aIsFirstPaint);
606 return NS_OK;
607 }
608 return NS_ERROR_FAILURE;
609 }
611 NS_IMETHODIMP
612 nsDOMWindowUtils::GetIsFirstPaint(bool *aIsFirstPaint)
613 {
614 if (!nsContentUtils::IsCallerChrome()) {
615 return NS_ERROR_DOM_SECURITY_ERR;
616 }
618 nsIPresShell* presShell = GetPresShell();
619 if (presShell) {
620 *aIsFirstPaint = presShell->GetIsFirstPaint();
621 return NS_OK;
622 }
623 return NS_ERROR_FAILURE;
624 }
626 NS_IMETHODIMP
627 nsDOMWindowUtils::GetPresShellId(uint32_t *aPresShellId)
628 {
629 if (!nsContentUtils::IsCallerChrome()) {
630 return NS_ERROR_DOM_SECURITY_ERR;
631 }
633 nsIPresShell* presShell = GetPresShell();
634 if (presShell) {
635 *aPresShellId = presShell->GetPresShellId();
636 return NS_OK;
637 }
638 return NS_ERROR_FAILURE;
639 }
641 /* static */
642 mozilla::Modifiers
643 nsDOMWindowUtils::GetWidgetModifiers(int32_t aModifiers)
644 {
645 Modifiers result = 0;
646 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
647 result |= mozilla::MODIFIER_SHIFT;
648 }
649 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
650 result |= mozilla::MODIFIER_CONTROL;
651 }
652 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
653 result |= mozilla::MODIFIER_ALT;
654 }
655 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
656 result |= mozilla::MODIFIER_META;
657 }
658 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
659 result |= mozilla::MODIFIER_ALTGRAPH;
660 }
661 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
662 result |= mozilla::MODIFIER_CAPSLOCK;
663 }
664 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
665 result |= mozilla::MODIFIER_FN;
666 }
667 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
668 result |= mozilla::MODIFIER_NUMLOCK;
669 }
670 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
671 result |= mozilla::MODIFIER_SCROLLLOCK;
672 }
673 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
674 result |= mozilla::MODIFIER_SYMBOLLOCK;
675 }
676 if (aModifiers & nsIDOMWindowUtils::MODIFIER_OS) {
677 result |= mozilla::MODIFIER_OS;
678 }
679 return result;
680 }
682 NS_IMETHODIMP
683 nsDOMWindowUtils::SendMouseEvent(const nsAString& aType,
684 float aX,
685 float aY,
686 int32_t aButton,
687 int32_t aClickCount,
688 int32_t aModifiers,
689 bool aIgnoreRootScrollFrame,
690 float aPressure,
691 unsigned short aInputSourceArg,
692 bool aIsSynthesized,
693 uint8_t aOptionalArgCount,
694 bool *aPreventDefault)
695 {
696 return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
697 aIgnoreRootScrollFrame, aPressure,
698 aInputSourceArg, false, aPreventDefault,
699 aOptionalArgCount >= 4 ? aIsSynthesized : true);
700 }
702 NS_IMETHODIMP
703 nsDOMWindowUtils::SendMouseEventToWindow(const nsAString& aType,
704 float aX,
705 float aY,
706 int32_t aButton,
707 int32_t aClickCount,
708 int32_t aModifiers,
709 bool aIgnoreRootScrollFrame,
710 float aPressure,
711 unsigned short aInputSourceArg,
712 bool aIsSynthesized,
713 uint8_t aOptionalArgCount)
714 {
715 PROFILER_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow");
716 return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
717 aIgnoreRootScrollFrame, aPressure,
718 aInputSourceArg, true, nullptr,
719 aOptionalArgCount >= 4 ? aIsSynthesized : true);
720 }
722 static LayoutDeviceIntPoint
723 ToWidgetPoint(const CSSPoint& aPoint, const nsPoint& aOffset,
724 nsPresContext* aPresContext)
725 {
726 return LayoutDeviceIntPoint::FromAppUnitsRounded(
727 CSSPoint::ToAppUnits(aPoint) + aOffset,
728 aPresContext->AppUnitsPerDevPixel());
729 }
731 static inline int16_t
732 GetButtonsFlagForButton(int32_t aButton)
733 {
734 switch (aButton) {
735 case WidgetMouseEvent::eLeftButton:
736 return WidgetMouseEvent::eLeftButtonFlag;
737 case WidgetMouseEvent::eMiddleButton:
738 return WidgetMouseEvent::eMiddleButtonFlag;
739 case WidgetMouseEvent::eRightButton:
740 return WidgetMouseEvent::eRightButtonFlag;
741 case 4:
742 return WidgetMouseEvent::e4thButtonFlag;
743 case 5:
744 return WidgetMouseEvent::e5thButtonFlag;
745 default:
746 NS_ERROR("Button not known.");
747 return 0;
748 }
749 }
751 NS_IMETHODIMP
752 nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
753 float aX,
754 float aY,
755 int32_t aButton,
756 int32_t aClickCount,
757 int32_t aModifiers,
758 bool aIgnoreRootScrollFrame,
759 float aPressure,
760 unsigned short aInputSourceArg,
761 bool aToWindow,
762 bool *aPreventDefault,
763 bool aIsSynthesized)
764 {
765 if (!nsContentUtils::IsCallerChrome()) {
766 return NS_ERROR_DOM_SECURITY_ERR;
767 }
769 // get the widget to send the event to
770 nsPoint offset;
771 nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
772 if (!widget)
773 return NS_ERROR_FAILURE;
775 int32_t msg;
776 bool contextMenuKey = false;
777 if (aType.EqualsLiteral("mousedown"))
778 msg = NS_MOUSE_BUTTON_DOWN;
779 else if (aType.EqualsLiteral("mouseup"))
780 msg = NS_MOUSE_BUTTON_UP;
781 else if (aType.EqualsLiteral("mousemove"))
782 msg = NS_MOUSE_MOVE;
783 else if (aType.EqualsLiteral("mouseover"))
784 msg = NS_MOUSE_ENTER;
785 else if (aType.EqualsLiteral("mouseout"))
786 msg = NS_MOUSE_EXIT;
787 else if (aType.EqualsLiteral("contextmenu")) {
788 msg = NS_CONTEXTMENU;
789 contextMenuKey = (aButton == 0);
790 } else if (aType.EqualsLiteral("MozMouseHittest"))
791 msg = NS_MOUSE_MOZHITTEST;
792 else
793 return NS_ERROR_FAILURE;
795 if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) {
796 aInputSourceArg = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
797 }
799 WidgetMouseEvent event(true, msg, widget, WidgetMouseEvent::eReal,
800 contextMenuKey ? WidgetMouseEvent::eContextMenuKey :
801 WidgetMouseEvent::eNormal);
802 event.modifiers = GetWidgetModifiers(aModifiers);
803 event.button = aButton;
804 event.buttons = GetButtonsFlagForButton(aButton);
805 event.widget = widget;
806 event.pressure = aPressure;
807 event.inputSource = aInputSourceArg;
808 event.clickCount = aClickCount;
809 event.time = PR_IntervalNow();
810 event.mFlags.mIsSynthesizedForTests = aIsSynthesized;
812 nsPresContext* presContext = GetPresContext();
813 if (!presContext)
814 return NS_ERROR_FAILURE;
816 event.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
817 event.ignoreRootScrollFrame = aIgnoreRootScrollFrame;
819 nsEventStatus status;
820 if (aToWindow) {
821 nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
822 if (!presShell)
823 return NS_ERROR_FAILURE;
824 nsViewManager* viewManager = presShell->GetViewManager();
825 if (!viewManager)
826 return NS_ERROR_FAILURE;
827 nsView* view = viewManager->GetRootView();
828 if (!view)
829 return NS_ERROR_FAILURE;
831 status = nsEventStatus_eIgnore;
832 return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
833 }
834 nsresult rv = widget->DispatchEvent(&event, status);
835 *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
837 return rv;
838 }
840 NS_IMETHODIMP
841 nsDOMWindowUtils::SendPointerEvent(const nsAString& aType,
842 float aX,
843 float aY,
844 int32_t aButton,
845 int32_t aClickCount,
846 int32_t aModifiers,
847 bool aIgnoreRootScrollFrame,
848 float aPressure,
849 unsigned short aInputSourceArg,
850 int32_t aPointerId,
851 int32_t aWidth,
852 int32_t aHeight,
853 int32_t tiltX,
854 int32_t tiltY,
855 bool aIsPrimary,
856 bool aIsSynthesized,
857 uint8_t aOptionalArgCount,
858 bool* aPreventDefault)
859 {
860 if (!nsContentUtils::IsCallerChrome()) {
861 return NS_ERROR_DOM_SECURITY_ERR;
862 }
864 // get the widget to send the event to
865 nsPoint offset;
866 nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
867 if (!widget) {
868 return NS_ERROR_FAILURE;
869 }
871 int32_t msg;
872 if (aType.EqualsLiteral("pointerdown")) {
873 msg = NS_POINTER_DOWN;
874 } else if (aType.EqualsLiteral("pointerup")) {
875 msg = NS_POINTER_UP;
876 } else if (aType.EqualsLiteral("pointermove")) {
877 msg = NS_POINTER_MOVE;
878 } else if (aType.EqualsLiteral("pointerover")) {
879 msg = NS_POINTER_OVER;
880 } else if (aType.EqualsLiteral("pointerout")) {
881 msg = NS_POINTER_OUT;
882 } else {
883 return NS_ERROR_FAILURE;
884 }
886 if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) {
887 aInputSourceArg = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
888 }
890 WidgetPointerEvent event(true, msg, widget);
891 event.modifiers = GetWidgetModifiers(aModifiers);
892 event.button = aButton;
893 event.buttons = GetButtonsFlagForButton(aButton);
894 event.widget = widget;
895 event.pressure = aPressure;
896 event.inputSource = aInputSourceArg;
897 event.pointerId = aPointerId;
898 event.width = aWidth;
899 event.height = aHeight;
900 event.tiltX = tiltX;
901 event.tiltY = tiltY;
902 event.isPrimary = aIsPrimary;
903 event.clickCount = aClickCount;
904 event.time = PR_IntervalNow();
905 event.mFlags.mIsSynthesizedForTests = aOptionalArgCount >= 10 ? aIsSynthesized : true;
907 nsPresContext* presContext = GetPresContext();
908 if (!presContext) {
909 return NS_ERROR_FAILURE;
910 }
912 event.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
913 event.ignoreRootScrollFrame = aIgnoreRootScrollFrame;
915 nsEventStatus status;
916 nsresult rv = widget->DispatchEvent(&event, status);
917 *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
919 return rv;
920 }
922 NS_IMETHODIMP
923 nsDOMWindowUtils::SendWheelEvent(float aX,
924 float aY,
925 double aDeltaX,
926 double aDeltaY,
927 double aDeltaZ,
928 uint32_t aDeltaMode,
929 int32_t aModifiers,
930 int32_t aLineOrPageDeltaX,
931 int32_t aLineOrPageDeltaY,
932 uint32_t aOptions)
933 {
934 if (!nsContentUtils::IsCallerChrome()) {
935 return NS_ERROR_DOM_SECURITY_ERR;
936 }
938 // get the widget to send the event to
939 nsPoint offset;
940 nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
941 if (!widget) {
942 return NS_ERROR_NULL_POINTER;
943 }
945 WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, widget);
946 wheelEvent.modifiers = GetWidgetModifiers(aModifiers);
947 wheelEvent.deltaX = aDeltaX;
948 wheelEvent.deltaY = aDeltaY;
949 wheelEvent.deltaZ = aDeltaZ;
950 wheelEvent.deltaMode = aDeltaMode;
951 wheelEvent.isMomentum =
952 (aOptions & WHEEL_EVENT_CAUSED_BY_MOMENTUM) != 0;
953 wheelEvent.isPixelOnlyDevice =
954 (aOptions & WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE) != 0;
955 NS_ENSURE_TRUE(
956 !wheelEvent.isPixelOnlyDevice ||
957 aDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL,
958 NS_ERROR_INVALID_ARG);
959 wheelEvent.customizedByUserPrefs =
960 (aOptions & WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS) != 0;
961 wheelEvent.lineOrPageDeltaX = aLineOrPageDeltaX;
962 wheelEvent.lineOrPageDeltaY = aLineOrPageDeltaY;
963 wheelEvent.widget = widget;
965 wheelEvent.time = PR_Now() / 1000;
967 nsPresContext* presContext = GetPresContext();
968 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
970 wheelEvent.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
972 nsEventStatus status;
973 nsresult rv = widget->DispatchEvent(&wheelEvent, status);
974 NS_ENSURE_SUCCESS(rv, rv);
976 bool failedX = false;
977 if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO) &&
978 wheelEvent.overflowDeltaX != 0) {
979 failedX = true;
980 }
981 if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_POSITIVE) &&
982 wheelEvent.overflowDeltaX <= 0) {
983 failedX = true;
984 }
985 if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_NEGATIVE) &&
986 wheelEvent.overflowDeltaX >= 0) {
987 failedX = true;
988 }
989 bool failedY = false;
990 if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_ZERO) &&
991 wheelEvent.overflowDeltaY != 0) {
992 failedY = true;
993 }
994 if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_POSITIVE) &&
995 wheelEvent.overflowDeltaY <= 0) {
996 failedY = true;
997 }
998 if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_NEGATIVE) &&
999 wheelEvent.overflowDeltaY >= 0) {
1000 failedY = true;
1001 }
1003 #ifdef DEBUG
1004 if (failedX) {
1005 nsPrintfCString debugMsg("SendWheelEvent(): unexpected overflowDeltaX: %f",
1006 wheelEvent.overflowDeltaX);
1007 NS_WARNING(debugMsg.get());
1008 }
1009 if (failedY) {
1010 nsPrintfCString debugMsg("SendWheelEvent(): unexpected overflowDeltaY: %f",
1011 wheelEvent.overflowDeltaY);
1012 NS_WARNING(debugMsg.get());
1013 }
1014 #endif
1016 return (!failedX && !failedY) ? NS_OK : NS_ERROR_FAILURE;
1017 }
1019 NS_IMETHODIMP
1020 nsDOMWindowUtils::SendTouchEvent(const nsAString& aType,
1021 uint32_t *aIdentifiers,
1022 int32_t *aXs,
1023 int32_t *aYs,
1024 uint32_t *aRxs,
1025 uint32_t *aRys,
1026 float *aRotationAngles,
1027 float *aForces,
1028 uint32_t aCount,
1029 int32_t aModifiers,
1030 bool aIgnoreRootScrollFrame,
1031 bool *aPreventDefault)
1032 {
1033 return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
1034 aRotationAngles, aForces, aCount, aModifiers,
1035 aIgnoreRootScrollFrame, false, aPreventDefault);
1036 }
1038 NS_IMETHODIMP
1039 nsDOMWindowUtils::SendTouchEventToWindow(const nsAString& aType,
1040 uint32_t* aIdentifiers,
1041 int32_t* aXs,
1042 int32_t* aYs,
1043 uint32_t* aRxs,
1044 uint32_t* aRys,
1045 float* aRotationAngles,
1046 float* aForces,
1047 uint32_t aCount,
1048 int32_t aModifiers,
1049 bool aIgnoreRootScrollFrame,
1050 bool* aPreventDefault)
1051 {
1052 return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
1053 aRotationAngles, aForces, aCount, aModifiers,
1054 aIgnoreRootScrollFrame, true, aPreventDefault);
1055 }
1057 NS_IMETHODIMP
1058 nsDOMWindowUtils::SendTouchEventCommon(const nsAString& aType,
1059 uint32_t* aIdentifiers,
1060 int32_t* aXs,
1061 int32_t* aYs,
1062 uint32_t* aRxs,
1063 uint32_t* aRys,
1064 float* aRotationAngles,
1065 float* aForces,
1066 uint32_t aCount,
1067 int32_t aModifiers,
1068 bool aIgnoreRootScrollFrame,
1069 bool aToWindow,
1070 bool* aPreventDefault)
1071 {
1072 if (!nsContentUtils::IsCallerChrome()) {
1073 return NS_ERROR_DOM_SECURITY_ERR;
1074 }
1076 // get the widget to send the event to
1077 nsPoint offset;
1078 nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
1079 if (!widget) {
1080 return NS_ERROR_NULL_POINTER;
1081 }
1082 int32_t msg;
1083 if (aType.EqualsLiteral("touchstart")) {
1084 msg = NS_TOUCH_START;
1085 } else if (aType.EqualsLiteral("touchmove")) {
1086 msg = NS_TOUCH_MOVE;
1087 } else if (aType.EqualsLiteral("touchend")) {
1088 msg = NS_TOUCH_END;
1089 } else if (aType.EqualsLiteral("touchcancel")) {
1090 msg = NS_TOUCH_CANCEL;
1091 } else {
1092 return NS_ERROR_UNEXPECTED;
1093 }
1094 WidgetTouchEvent event(true, msg, widget);
1095 event.modifiers = GetWidgetModifiers(aModifiers);
1096 event.widget = widget;
1097 event.time = PR_Now();
1099 nsPresContext* presContext = GetPresContext();
1100 if (!presContext) {
1101 return NS_ERROR_FAILURE;
1102 }
1103 event.touches.SetCapacity(aCount);
1104 for (uint32_t i = 0; i < aCount; ++i) {
1105 LayoutDeviceIntPoint pt =
1106 ToWidgetPoint(CSSPoint(aXs[i], aYs[i]), offset, presContext);
1107 nsRefPtr<Touch> t = new Touch(aIdentifiers[i],
1108 LayoutDeviceIntPoint::ToUntyped(pt),
1109 nsIntPoint(aRxs[i], aRys[i]),
1110 aRotationAngles[i],
1111 aForces[i]);
1112 event.touches.AppendElement(t);
1113 }
1115 nsEventStatus status;
1116 if (aToWindow) {
1117 nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
1118 if (!presShell) {
1119 return NS_ERROR_FAILURE;
1120 }
1122 nsViewManager* viewManager = presShell->GetViewManager();
1123 if (!viewManager) {
1124 return NS_ERROR_FAILURE;
1125 }
1127 nsView* view = viewManager->GetRootView();
1128 if (!view) {
1129 return NS_ERROR_FAILURE;
1130 }
1132 status = nsEventStatus_eIgnore;
1133 *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
1134 return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
1135 }
1137 nsresult rv = widget->DispatchEvent(&event, status);
1138 *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
1139 return rv;
1140 }
1142 NS_IMETHODIMP
1143 nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
1144 int32_t aKeyCode,
1145 int32_t aCharCode,
1146 int32_t aModifiers,
1147 uint32_t aAdditionalFlags,
1148 bool* aDefaultActionTaken)
1149 {
1150 if (!nsContentUtils::IsCallerChrome()) {
1151 return NS_ERROR_DOM_SECURITY_ERR;
1152 }
1154 // get the widget to send the event to
1155 nsCOMPtr<nsIWidget> widget = GetWidget();
1156 if (!widget)
1157 return NS_ERROR_FAILURE;
1159 int32_t msg;
1160 if (aType.EqualsLiteral("keydown"))
1161 msg = NS_KEY_DOWN;
1162 else if (aType.EqualsLiteral("keyup"))
1163 msg = NS_KEY_UP;
1164 else if (aType.EqualsLiteral("keypress"))
1165 msg = NS_KEY_PRESS;
1166 else
1167 return NS_ERROR_FAILURE;
1169 WidgetKeyboardEvent event(true, msg, widget);
1170 event.modifiers = GetWidgetModifiers(aModifiers);
1172 if (msg == NS_KEY_PRESS) {
1173 event.keyCode = aCharCode ? 0 : aKeyCode;
1174 event.charCode = aCharCode;
1175 } else {
1176 event.keyCode = aKeyCode;
1177 event.charCode = 0;
1178 }
1180 uint32_t locationFlag = (aAdditionalFlags &
1181 (KEY_FLAG_LOCATION_STANDARD | KEY_FLAG_LOCATION_LEFT |
1182 KEY_FLAG_LOCATION_RIGHT | KEY_FLAG_LOCATION_NUMPAD |
1183 KEY_FLAG_LOCATION_MOBILE | KEY_FLAG_LOCATION_JOYSTICK));
1184 switch (locationFlag) {
1185 case KEY_FLAG_LOCATION_STANDARD:
1186 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD;
1187 break;
1188 case KEY_FLAG_LOCATION_LEFT:
1189 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT;
1190 break;
1191 case KEY_FLAG_LOCATION_RIGHT:
1192 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT;
1193 break;
1194 case KEY_FLAG_LOCATION_NUMPAD:
1195 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
1196 break;
1197 case KEY_FLAG_LOCATION_MOBILE:
1198 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_MOBILE;
1199 break;
1200 case KEY_FLAG_LOCATION_JOYSTICK:
1201 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_JOYSTICK;
1202 break;
1203 default:
1204 if (locationFlag != 0) {
1205 return NS_ERROR_INVALID_ARG;
1206 }
1207 // If location flag isn't set, choose the location from keycode.
1208 switch (aKeyCode) {
1209 case nsIDOMKeyEvent::DOM_VK_NUMPAD0:
1210 case nsIDOMKeyEvent::DOM_VK_NUMPAD1:
1211 case nsIDOMKeyEvent::DOM_VK_NUMPAD2:
1212 case nsIDOMKeyEvent::DOM_VK_NUMPAD3:
1213 case nsIDOMKeyEvent::DOM_VK_NUMPAD4:
1214 case nsIDOMKeyEvent::DOM_VK_NUMPAD5:
1215 case nsIDOMKeyEvent::DOM_VK_NUMPAD6:
1216 case nsIDOMKeyEvent::DOM_VK_NUMPAD7:
1217 case nsIDOMKeyEvent::DOM_VK_NUMPAD8:
1218 case nsIDOMKeyEvent::DOM_VK_NUMPAD9:
1219 case nsIDOMKeyEvent::DOM_VK_MULTIPLY:
1220 case nsIDOMKeyEvent::DOM_VK_ADD:
1221 case nsIDOMKeyEvent::DOM_VK_SEPARATOR:
1222 case nsIDOMKeyEvent::DOM_VK_SUBTRACT:
1223 case nsIDOMKeyEvent::DOM_VK_DECIMAL:
1224 case nsIDOMKeyEvent::DOM_VK_DIVIDE:
1225 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
1226 break;
1227 case nsIDOMKeyEvent::DOM_VK_SHIFT:
1228 case nsIDOMKeyEvent::DOM_VK_CONTROL:
1229 case nsIDOMKeyEvent::DOM_VK_ALT:
1230 case nsIDOMKeyEvent::DOM_VK_META:
1231 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT;
1232 break;
1233 default:
1234 event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD;
1235 break;
1236 }
1237 break;
1238 }
1240 event.refPoint.x = event.refPoint.y = 0;
1241 event.time = PR_IntervalNow();
1242 event.mFlags.mIsSynthesizedForTests = true;
1244 if (aAdditionalFlags & KEY_FLAG_PREVENT_DEFAULT) {
1245 event.mFlags.mDefaultPrevented = true;
1246 }
1248 nsEventStatus status;
1249 nsresult rv = widget->DispatchEvent(&event, status);
1250 NS_ENSURE_SUCCESS(rv, rv);
1252 *aDefaultActionTaken = (status != nsEventStatus_eConsumeNoDefault);
1254 return NS_OK;
1255 }
1257 NS_IMETHODIMP
1258 nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
1259 int32_t aNativeKeyCode,
1260 int32_t aModifiers,
1261 const nsAString& aCharacters,
1262 const nsAString& aUnmodifiedCharacters)
1263 {
1264 if (!nsContentUtils::IsCallerChrome()) {
1265 return NS_ERROR_DOM_SECURITY_ERR;
1266 }
1268 // get the widget to send the event to
1269 nsCOMPtr<nsIWidget> widget = GetWidget();
1270 if (!widget)
1271 return NS_ERROR_FAILURE;
1273 return widget->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
1274 aModifiers, aCharacters, aUnmodifiedCharacters);
1275 }
1277 NS_IMETHODIMP
1278 nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX,
1279 int32_t aScreenY,
1280 int32_t aNativeMessage,
1281 int32_t aModifierFlags,
1282 nsIDOMElement* aElement)
1283 {
1284 if (!nsContentUtils::IsCallerChrome()) {
1285 return NS_ERROR_DOM_SECURITY_ERR;
1286 }
1288 // get the widget to send the event to
1289 nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
1290 if (!widget)
1291 return NS_ERROR_FAILURE;
1293 return widget->SynthesizeNativeMouseEvent(nsIntPoint(aScreenX, aScreenY),
1294 aNativeMessage, aModifierFlags);
1295 }
1297 NS_IMETHODIMP
1298 nsDOMWindowUtils::SendNativeMouseScrollEvent(int32_t aScreenX,
1299 int32_t aScreenY,
1300 uint32_t aNativeMessage,
1301 double aDeltaX,
1302 double aDeltaY,
1303 double aDeltaZ,
1304 uint32_t aModifierFlags,
1305 uint32_t aAdditionalFlags,
1306 nsIDOMElement* aElement)
1307 {
1308 if (!nsContentUtils::IsCallerChrome()) {
1309 return NS_ERROR_DOM_SECURITY_ERR;
1310 }
1312 // get the widget to send the event to
1313 nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
1314 if (!widget) {
1315 return NS_ERROR_FAILURE;
1316 }
1318 return widget->SynthesizeNativeMouseScrollEvent(nsIntPoint(aScreenX,
1319 aScreenY),
1320 aNativeMessage,
1321 aDeltaX, aDeltaY, aDeltaZ,
1322 aModifierFlags,
1323 aAdditionalFlags);
1324 }
1326 NS_IMETHODIMP
1327 nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
1328 uint32_t aTouchState,
1329 int32_t aScreenX,
1330 int32_t aScreenY,
1331 double aPressure,
1332 uint32_t aOrientation)
1333 {
1334 if (!nsContentUtils::IsCallerChrome()) {
1335 return NS_ERROR_DOM_SECURITY_ERR;
1336 }
1338 nsCOMPtr<nsIWidget> widget = GetWidget();
1339 if (!widget) {
1340 return NS_ERROR_FAILURE;
1341 }
1343 if (aPressure < 0 || aPressure > 1 || aOrientation > 359) {
1344 return NS_ERROR_INVALID_ARG;
1345 }
1347 return widget->SynthesizeNativeTouchPoint(aPointerId,
1348 (nsIWidget::TouchPointerState)aTouchState,
1349 nsIntPoint(aScreenX, aScreenY),
1350 aPressure, aOrientation);
1351 }
1353 NS_IMETHODIMP
1354 nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX,
1355 int32_t aScreenY,
1356 bool aLongTap)
1357 {
1358 if (!nsContentUtils::IsCallerChrome()) {
1359 return NS_ERROR_DOM_SECURITY_ERR;
1360 }
1362 nsCOMPtr<nsIWidget> widget = GetWidget();
1363 if (!widget) {
1364 return NS_ERROR_FAILURE;
1365 }
1366 return widget->SynthesizeNativeTouchTap(nsIntPoint(aScreenX, aScreenY), aLongTap);
1367 }
1369 NS_IMETHODIMP
1370 nsDOMWindowUtils::ClearNativeTouchSequence()
1371 {
1372 if (!nsContentUtils::IsCallerChrome()) {
1373 return NS_ERROR_DOM_SECURITY_ERR;
1374 }
1376 nsCOMPtr<nsIWidget> widget = GetWidget();
1377 if (!widget) {
1378 return NS_ERROR_FAILURE;
1379 }
1380 return widget->ClearNativeTouchSequence();
1381 }
1383 NS_IMETHODIMP
1384 nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString& indexString)
1385 {
1386 if (!nsContentUtils::IsCallerChrome()) {
1387 return NS_ERROR_DOM_SECURITY_ERR;
1388 }
1390 // get the widget to send the event to
1391 nsCOMPtr<nsIWidget> widget = GetWidget();
1392 if (!widget)
1393 return NS_ERROR_FAILURE;
1395 return widget->ActivateNativeMenuItemAt(indexString);
1396 }
1398 NS_IMETHODIMP
1399 nsDOMWindowUtils::ForceUpdateNativeMenuAt(const nsAString& indexString)
1400 {
1401 if (!nsContentUtils::IsCallerChrome()) {
1402 return NS_ERROR_DOM_SECURITY_ERR;
1403 }
1405 // get the widget to send the event to
1406 nsCOMPtr<nsIWidget> widget = GetWidget();
1407 if (!widget)
1408 return NS_ERROR_FAILURE;
1410 return widget->ForceUpdateNativeMenuAt(indexString);
1411 }
1413 nsIWidget*
1414 nsDOMWindowUtils::GetWidget(nsPoint* aOffset)
1415 {
1416 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
1417 if (window) {
1418 nsIDocShell *docShell = window->GetDocShell();
1419 if (docShell) {
1420 nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
1421 if (presShell) {
1422 nsIFrame* frame = presShell->GetRootFrame();
1423 if (frame)
1424 return frame->GetView()->GetNearestWidget(aOffset);
1425 }
1426 }
1427 }
1429 return nullptr;
1430 }
1432 nsIWidget*
1433 nsDOMWindowUtils::GetWidgetForElement(nsIDOMElement* aElement)
1434 {
1435 if (!aElement)
1436 return GetWidget();
1438 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
1439 nsIDocument* doc = content->GetCurrentDoc();
1440 nsIPresShell* presShell = doc ? doc->GetShell() : nullptr;
1442 if (presShell) {
1443 nsIFrame* frame = content->GetPrimaryFrame();
1444 if (!frame) {
1445 frame = presShell->GetRootFrame();
1446 }
1447 if (frame)
1448 return frame->GetNearestWidget();
1449 }
1451 return nullptr;
1452 }
1454 NS_IMETHODIMP
1455 nsDOMWindowUtils::Focus(nsIDOMElement* aElement)
1456 {
1457 if (!nsContentUtils::IsCallerChrome()) {
1458 return NS_ERROR_DOM_SECURITY_ERR;
1459 }
1461 nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindow);
1462 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
1463 if (fm) {
1464 if (aElement)
1465 fm->SetFocus(aElement, 0);
1466 else
1467 fm->ClearFocus(window);
1468 }
1470 return NS_OK;
1471 }
1473 NS_IMETHODIMP
1474 nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener,
1475 int32_t aExtraForgetSkippableCalls)
1476 {
1477 PROFILER_LABEL("GC", "GarbageCollect");
1478 // Always permit this in debug builds.
1479 #ifndef DEBUG
1480 if (!nsContentUtils::IsCallerChrome()) {
1481 return NS_ERROR_DOM_SECURITY_ERR;
1482 }
1483 #endif
1485 nsJSContext::GarbageCollectNow(JS::gcreason::DOM_UTILS);
1486 nsJSContext::CycleCollectNow(aListener, aExtraForgetSkippableCalls);
1488 return NS_OK;
1489 }
1491 NS_IMETHODIMP
1492 nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener *aListener,
1493 int32_t aExtraForgetSkippableCalls)
1494 {
1495 // Always permit this in debug builds.
1496 #ifndef DEBUG
1497 if (!nsContentUtils::IsCallerChrome()) {
1498 return NS_ERROR_DOM_SECURITY_ERR;
1499 }
1500 #endif
1502 nsJSContext::CycleCollectNow(aListener, aExtraForgetSkippableCalls);
1503 return NS_OK;
1504 }
1506 NS_IMETHODIMP
1507 nsDOMWindowUtils::RunNextCollectorTimer()
1508 {
1509 if (!nsContentUtils::IsCallerChrome()) {
1510 return NS_ERROR_DOM_SECURITY_ERR;
1511 }
1513 nsJSContext::RunNextCollectorTimer();
1515 return NS_OK;
1516 }
1518 NS_IMETHODIMP
1519 nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString& aType,
1520 float aX,
1521 float aY,
1522 uint32_t aDirection,
1523 double aDelta,
1524 int32_t aModifiers,
1525 uint32_t aClickCount)
1526 {
1527 if (!nsContentUtils::IsCallerChrome()) {
1528 return NS_ERROR_DOM_SECURITY_ERR;
1529 }
1531 // get the widget to send the event to
1532 nsPoint offset;
1533 nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
1534 if (!widget)
1535 return NS_ERROR_FAILURE;
1537 int32_t msg;
1538 if (aType.EqualsLiteral("MozSwipeGestureStart"))
1539 msg = NS_SIMPLE_GESTURE_SWIPE_START;
1540 else if (aType.EqualsLiteral("MozSwipeGestureUpdate"))
1541 msg = NS_SIMPLE_GESTURE_SWIPE_UPDATE;
1542 else if (aType.EqualsLiteral("MozSwipeGestureEnd"))
1543 msg = NS_SIMPLE_GESTURE_SWIPE_END;
1544 else if (aType.EqualsLiteral("MozSwipeGesture"))
1545 msg = NS_SIMPLE_GESTURE_SWIPE;
1546 else if (aType.EqualsLiteral("MozMagnifyGestureStart"))
1547 msg = NS_SIMPLE_GESTURE_MAGNIFY_START;
1548 else if (aType.EqualsLiteral("MozMagnifyGestureUpdate"))
1549 msg = NS_SIMPLE_GESTURE_MAGNIFY_UPDATE;
1550 else if (aType.EqualsLiteral("MozMagnifyGesture"))
1551 msg = NS_SIMPLE_GESTURE_MAGNIFY;
1552 else if (aType.EqualsLiteral("MozRotateGestureStart"))
1553 msg = NS_SIMPLE_GESTURE_ROTATE_START;
1554 else if (aType.EqualsLiteral("MozRotateGestureUpdate"))
1555 msg = NS_SIMPLE_GESTURE_ROTATE_UPDATE;
1556 else if (aType.EqualsLiteral("MozRotateGesture"))
1557 msg = NS_SIMPLE_GESTURE_ROTATE;
1558 else if (aType.EqualsLiteral("MozTapGesture"))
1559 msg = NS_SIMPLE_GESTURE_TAP;
1560 else if (aType.EqualsLiteral("MozPressTapGesture"))
1561 msg = NS_SIMPLE_GESTURE_PRESSTAP;
1562 else if (aType.EqualsLiteral("MozEdgeUIStarted"))
1563 msg = NS_SIMPLE_GESTURE_EDGE_STARTED;
1564 else if (aType.EqualsLiteral("MozEdgeUICanceled"))
1565 msg = NS_SIMPLE_GESTURE_EDGE_CANCELED;
1566 else if (aType.EqualsLiteral("MozEdgeUICompleted"))
1567 msg = NS_SIMPLE_GESTURE_EDGE_COMPLETED;
1568 else
1569 return NS_ERROR_FAILURE;
1571 WidgetSimpleGestureEvent event(true, msg, widget);
1572 event.modifiers = GetWidgetModifiers(aModifiers);
1573 event.direction = aDirection;
1574 event.delta = aDelta;
1575 event.clickCount = aClickCount;
1576 event.time = PR_IntervalNow();
1578 nsPresContext* presContext = GetPresContext();
1579 if (!presContext)
1580 return NS_ERROR_FAILURE;
1582 event.refPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
1584 nsEventStatus status;
1585 return widget->DispatchEvent(&event, status);
1586 }
1588 NS_IMETHODIMP
1589 nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
1590 bool aIgnoreRootScrollFrame,
1591 bool aFlushLayout,
1592 nsIDOMElement** aReturn)
1593 {
1594 if (!nsContentUtils::IsCallerChrome()) {
1595 return NS_ERROR_DOM_SECURITY_ERR;
1596 }
1598 nsCOMPtr<nsIDocument> doc = GetDocument();
1599 NS_ENSURE_STATE(doc);
1601 Element* el =
1602 doc->ElementFromPointHelper(aX, aY, aIgnoreRootScrollFrame, aFlushLayout);
1603 nsCOMPtr<nsIDOMElement> retval = do_QueryInterface(el);
1604 retval.forget(aReturn);
1605 return NS_OK;
1606 }
1608 NS_IMETHODIMP
1609 nsDOMWindowUtils::NodesFromRect(float aX, float aY,
1610 float aTopSize, float aRightSize,
1611 float aBottomSize, float aLeftSize,
1612 bool aIgnoreRootScrollFrame,
1613 bool aFlushLayout,
1614 nsIDOMNodeList** aReturn)
1615 {
1616 if (!nsContentUtils::IsCallerChrome()) {
1617 return NS_ERROR_DOM_SECURITY_ERR;
1618 }
1620 nsCOMPtr<nsIDocument> doc = GetDocument();
1621 NS_ENSURE_STATE(doc);
1623 return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
1624 aIgnoreRootScrollFrame, aFlushLayout, aReturn);
1625 }
1627 NS_IMETHODIMP
1628 nsDOMWindowUtils::GetTranslationNodes(nsIDOMNode* aRoot,
1629 nsITranslationNodeList** aRetVal)
1630 {
1631 if (!nsContentUtils::IsCallerChrome()) {
1632 return NS_ERROR_DOM_SECURITY_ERR;
1633 }
1635 NS_ENSURE_ARG_POINTER(aRetVal);
1636 nsCOMPtr<nsIContent> root = do_QueryInterface(aRoot);
1637 NS_ENSURE_STATE(root);
1638 nsCOMPtr<nsIDocument> doc = GetDocument();
1639 NS_ENSURE_STATE(doc);
1641 if (root->OwnerDoc() != doc) {
1642 return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
1643 }
1645 nsTHashtable<nsPtrHashKey<nsIContent>> translationNodesHash(1000);
1646 nsRefPtr<nsTranslationNodeList> list = new nsTranslationNodeList;
1648 uint32_t limit = 15000;
1650 // We begin iteration with content->GetNextNode because we want to explictly
1651 // skip the root tag from being a translation node.
1652 nsIContent* content = root;
1653 while ((limit > 0) && (content = content->GetNextNode(root))) {
1654 if (!content->IsHTML()) {
1655 continue;
1656 }
1658 nsIAtom* localName = content->Tag();
1660 // Skip elements that usually contain non-translatable text content.
1661 if (localName == nsGkAtoms::script ||
1662 localName == nsGkAtoms::iframe ||
1663 localName == nsGkAtoms::frameset ||
1664 localName == nsGkAtoms::frame ||
1665 localName == nsGkAtoms::code ||
1666 localName == nsGkAtoms::noscript ||
1667 localName == nsGkAtoms::style) {
1668 continue;
1669 }
1671 // An element is a translation node if it contains
1672 // at least one text node that has meaningful data
1673 // for translation
1674 for (nsIContent* child = content->GetFirstChild();
1675 child;
1676 child = child->GetNextSibling()) {
1678 if (child->HasTextForTranslation()) {
1679 translationNodesHash.PutEntry(content);
1681 bool isBlockFrame = false;
1682 nsIFrame* frame = content->GetPrimaryFrame();
1683 if (frame) {
1684 isBlockFrame = frame->IsFrameOfType(nsIFrame::eBlockFrame);
1685 }
1687 bool isTranslationRoot = isBlockFrame;
1688 if (!isBlockFrame) {
1689 // If an element is not a block element, it still
1690 // can be considered a translation root if the parent
1691 // of this element didn't make into the list of nodes
1692 // to be translated.
1693 bool parentInList = false;
1694 nsIContent* parent = content->GetParent();
1695 if (parent) {
1696 parentInList = translationNodesHash.Contains(parent);
1697 }
1698 isTranslationRoot = !parentInList;
1699 }
1701 list->AppendElement(content->AsDOMNode(), isTranslationRoot);
1702 --limit;
1703 break;
1704 }
1705 }
1706 }
1708 *aRetVal = list.forget().take();
1709 return NS_OK;
1710 }
1712 static TemporaryRef<DataSourceSurface>
1713 CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas)
1714 {
1715 nsCOMPtr<nsINode> node = do_QueryInterface(aCanvas);
1716 if (!node) {
1717 return nullptr;
1718 }
1720 NS_ABORT_IF_FALSE(node->IsElement(),
1721 "An nsINode that implements nsIDOMHTMLCanvasElement should "
1722 "be an element.");
1723 nsLayoutUtils::SurfaceFromElementResult result =
1724 nsLayoutUtils::SurfaceFromElement(node->AsElement());
1725 return result.mSourceSurface->GetDataSurface();
1726 }
1728 NS_IMETHODIMP
1729 nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
1730 nsIDOMHTMLCanvasElement *aCanvas2,
1731 uint32_t* aMaxDifference,
1732 uint32_t* retVal)
1733 {
1734 if (!nsContentUtils::IsCallerChrome()) {
1735 return NS_ERROR_DOM_SECURITY_ERR;
1736 }
1738 if (aCanvas1 == nullptr ||
1739 aCanvas2 == nullptr ||
1740 retVal == nullptr)
1741 return NS_ERROR_FAILURE;
1743 RefPtr<DataSourceSurface> img1 = CanvasToDataSourceSurface(aCanvas1);
1744 RefPtr<DataSourceSurface> img2 = CanvasToDataSourceSurface(aCanvas2);
1746 if (img1 == nullptr || img2 == nullptr ||
1747 img1->GetSize() != img2->GetSize() ||
1748 img1->Stride() != img2->Stride())
1749 return NS_ERROR_FAILURE;
1751 int v;
1752 IntSize size = img1->GetSize();
1753 uint32_t stride = img1->Stride();
1755 // we can optimize for the common all-pass case
1756 if (stride == (uint32_t) size.width * 4) {
1757 v = memcmp(img1->GetData(), img2->GetData(), size.width * size.height * 4);
1758 if (v == 0) {
1759 if (aMaxDifference)
1760 *aMaxDifference = 0;
1761 *retVal = 0;
1762 return NS_OK;
1763 }
1764 }
1766 uint32_t dc = 0;
1767 uint32_t different = 0;
1769 for (int j = 0; j < size.height; j++) {
1770 unsigned char *p1 = img1->GetData() + j*stride;
1771 unsigned char *p2 = img2->GetData() + j*stride;
1772 v = memcmp(p1, p2, stride);
1774 if (v) {
1775 for (int i = 0; i < size.width; i++) {
1776 if (*(uint32_t*) p1 != *(uint32_t*) p2) {
1778 different++;
1780 dc = std::max((uint32_t)abs(p1[0] - p2[0]), dc);
1781 dc = std::max((uint32_t)abs(p1[1] - p2[1]), dc);
1782 dc = std::max((uint32_t)abs(p1[2] - p2[2]), dc);
1783 dc = std::max((uint32_t)abs(p1[3] - p2[3]), dc);
1784 }
1786 p1 += 4;
1787 p2 += 4;
1788 }
1789 }
1790 }
1792 if (aMaxDifference)
1793 *aMaxDifference = dc;
1795 *retVal = different;
1796 return NS_OK;
1797 }
1799 NS_IMETHODIMP
1800 nsDOMWindowUtils::GetIsMozAfterPaintPending(bool *aResult)
1801 {
1802 if (!nsContentUtils::IsCallerChrome()) {
1803 return NS_ERROR_DOM_SECURITY_ERR;
1804 }
1806 NS_ENSURE_ARG_POINTER(aResult);
1807 *aResult = false;
1808 nsPresContext* presContext = GetPresContext();
1809 if (!presContext)
1810 return NS_OK;
1811 *aResult = presContext->IsDOMPaintEventPending();
1812 return NS_OK;
1813 }
1815 NS_IMETHODIMP
1816 nsDOMWindowUtils::ClearMozAfterPaintEvents()
1817 {
1818 if (!nsContentUtils::IsCallerChrome()) {
1819 return NS_ERROR_DOM_SECURITY_ERR;
1820 }
1822 nsPresContext* presContext = GetPresContext();
1823 if (!presContext)
1824 return NS_OK;
1825 presContext->ClearMozAfterPaintEvents();
1826 return NS_OK;
1827 }
1829 NS_IMETHODIMP
1830 nsDOMWindowUtils::DisableNonTestMouseEvents(bool aDisable)
1831 {
1832 if (!nsContentUtils::IsCallerChrome()) {
1833 return NS_ERROR_DOM_SECURITY_ERR;
1834 }
1836 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
1837 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
1838 nsIDocShell *docShell = window->GetDocShell();
1839 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
1840 nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
1841 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
1842 presShell->DisableNonTestMouseEvents(aDisable);
1843 return NS_OK;
1844 }
1846 NS_IMETHODIMP
1847 nsDOMWindowUtils::SuppressEventHandling(bool aSuppress)
1848 {
1849 if (!nsContentUtils::IsCallerChrome()) {
1850 return NS_ERROR_DOM_SECURITY_ERR;
1851 }
1853 nsCOMPtr<nsIDocument> doc = GetDocument();
1854 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
1856 if (aSuppress) {
1857 doc->SuppressEventHandling(nsIDocument::eEvents);
1858 } else {
1859 doc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, true);
1860 }
1862 return NS_OK;
1863 }
1865 static nsresult
1866 getScrollXYAppUnits(nsWeakPtr aWindow, bool aFlushLayout, nsPoint& aScrollPos) {
1867 if (!nsContentUtils::IsCallerChrome()) {
1868 return NS_ERROR_DOM_SECURITY_ERR;
1869 }
1871 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(aWindow);
1872 nsCOMPtr<nsIDocument> doc = window ? window->GetExtantDoc() : nullptr;
1873 NS_ENSURE_STATE(doc);
1875 if (aFlushLayout) {
1876 doc->FlushPendingNotifications(Flush_Layout);
1877 }
1879 nsIPresShell *presShell = doc->GetShell();
1880 if (presShell) {
1881 nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
1882 if (sf) {
1883 aScrollPos = sf->GetScrollPosition();
1884 }
1885 }
1886 return NS_OK;
1887 }
1889 NS_IMETHODIMP
1890 nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aScrollY)
1891 {
1892 nsPoint scrollPos(0,0);
1893 nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
1894 NS_ENSURE_SUCCESS(rv, rv);
1895 *aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x);
1896 *aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);
1898 return NS_OK;
1899 }
1901 NS_IMETHODIMP
1902 nsDOMWindowUtils::GetScrollXYFloat(bool aFlushLayout, float* aScrollX, float* aScrollY)
1903 {
1904 nsPoint scrollPos(0,0);
1905 nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
1906 NS_ENSURE_SUCCESS(rv, rv);
1907 *aScrollX = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.x);
1908 *aScrollY = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.y);
1910 return NS_OK;
1911 }
1913 NS_IMETHODIMP
1914 nsDOMWindowUtils::GetScrollbarSize(bool aFlushLayout, int32_t* aWidth,
1915 int32_t* aHeight)
1916 {
1917 if (!nsContentUtils::IsCallerChrome()) {
1918 return NS_ERROR_DOM_SECURITY_ERR;
1919 }
1921 *aWidth = 0;
1922 *aHeight = 0;
1924 nsCOMPtr<nsIDocument> doc = GetDocument();
1925 NS_ENSURE_STATE(doc);
1927 if (aFlushLayout) {
1928 doc->FlushPendingNotifications(Flush_Layout);
1929 }
1931 nsIPresShell* presShell = doc->GetShell();
1932 NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
1934 nsIScrollableFrame* scrollFrame = presShell->GetRootScrollFrameAsScrollable();
1935 NS_ENSURE_TRUE(scrollFrame, NS_OK);
1937 nsMargin sizes = scrollFrame->GetActualScrollbarSizes();
1938 *aWidth = nsPresContext::AppUnitsToIntCSSPixels(sizes.LeftRight());
1939 *aHeight = nsPresContext::AppUnitsToIntCSSPixels(sizes.TopBottom());
1941 return NS_OK;
1942 }
1944 NS_IMETHODIMP
1945 nsDOMWindowUtils::GetBoundsWithoutFlushing(nsIDOMElement *aElement,
1946 nsIDOMClientRect** aResult)
1947 {
1948 if (!nsContentUtils::IsCallerChrome()) {
1949 return NS_ERROR_DOM_SECURITY_ERR;
1950 }
1952 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
1953 NS_ENSURE_STATE(window);
1955 nsresult rv;
1956 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
1957 NS_ENSURE_SUCCESS(rv, rv);
1959 nsRefPtr<DOMRect> rect = new DOMRect(window);
1960 nsIFrame* frame = content->GetPrimaryFrame();
1962 if (frame) {
1963 nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
1964 nsLayoutUtils::GetContainingBlockForClientRect(frame),
1965 nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
1966 rect->SetLayoutRect(r);
1967 }
1969 rect.forget(aResult);
1970 return NS_OK;
1971 }
1973 NS_IMETHODIMP
1974 nsDOMWindowUtils::GetRootBounds(nsIDOMClientRect** aResult)
1975 {
1976 if (!nsContentUtils::IsCallerChrome()) {
1977 return NS_ERROR_DOM_SECURITY_ERR;
1978 }
1980 nsIDocument* doc = GetDocument();
1981 NS_ENSURE_STATE(doc);
1983 nsRect bounds(0, 0, 0, 0);
1984 nsIPresShell* presShell = doc->GetShell();
1985 if (presShell) {
1986 nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
1987 if (sf) {
1988 bounds = sf->GetScrollRange();
1989 bounds.width += sf->GetScrollPortRect().width;
1990 bounds.height += sf->GetScrollPortRect().height;
1991 } else if (presShell->GetRootFrame()) {
1992 bounds = presShell->GetRootFrame()->GetRect();
1993 }
1994 }
1996 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
1997 nsRefPtr<DOMRect> rect = new DOMRect(window);
1998 rect->SetRect(nsPresContext::AppUnitsToFloatCSSPixels(bounds.x),
1999 nsPresContext::AppUnitsToFloatCSSPixels(bounds.y),
2000 nsPresContext::AppUnitsToFloatCSSPixels(bounds.width),
2001 nsPresContext::AppUnitsToFloatCSSPixels(bounds.height));
2002 rect.forget(aResult);
2003 return NS_OK;
2004 }
2006 NS_IMETHODIMP
2007 nsDOMWindowUtils::GetIMEIsOpen(bool *aState)
2008 {
2009 if (!nsContentUtils::IsCallerChrome()) {
2010 return NS_ERROR_DOM_SECURITY_ERR;
2011 }
2013 NS_ENSURE_ARG_POINTER(aState);
2015 nsCOMPtr<nsIWidget> widget = GetWidget();
2016 if (!widget)
2017 return NS_ERROR_FAILURE;
2019 // Open state should not be available when IME is not enabled.
2020 InputContext context = widget->GetInputContext();
2021 if (context.mIMEState.mEnabled != IMEState::ENABLED) {
2022 return NS_ERROR_NOT_AVAILABLE;
2023 }
2025 if (context.mIMEState.mOpen == IMEState::OPEN_STATE_NOT_SUPPORTED) {
2026 return NS_ERROR_NOT_IMPLEMENTED;
2027 }
2028 *aState = (context.mIMEState.mOpen == IMEState::OPEN);
2029 return NS_OK;
2030 }
2032 NS_IMETHODIMP
2033 nsDOMWindowUtils::GetIMEStatus(uint32_t *aState)
2034 {
2035 if (!nsContentUtils::IsCallerChrome()) {
2036 return NS_ERROR_DOM_SECURITY_ERR;
2037 }
2039 NS_ENSURE_ARG_POINTER(aState);
2041 nsCOMPtr<nsIWidget> widget = GetWidget();
2042 if (!widget)
2043 return NS_ERROR_FAILURE;
2045 InputContext context = widget->GetInputContext();
2046 *aState = static_cast<uint32_t>(context.mIMEState.mEnabled);
2047 return NS_OK;
2048 }
2050 NS_IMETHODIMP
2051 nsDOMWindowUtils::GetFocusedInputType(char** aType)
2052 {
2053 if (!nsContentUtils::IsCallerChrome()) {
2054 return NS_ERROR_DOM_SECURITY_ERR;
2055 }
2057 NS_ENSURE_ARG_POINTER(aType);
2059 nsCOMPtr<nsIWidget> widget = GetWidget();
2060 if (!widget) {
2061 return NS_ERROR_FAILURE;
2062 }
2064 InputContext context = widget->GetInputContext();
2065 *aType = ToNewCString(context.mHTMLInputType);
2066 return NS_OK;
2067 }
2069 NS_IMETHODIMP
2070 nsDOMWindowUtils::FindElementWithViewId(nsViewID aID,
2071 nsIDOMElement** aResult)
2072 {
2073 if (!nsContentUtils::IsCallerChrome()) {
2074 return NS_ERROR_DOM_SECURITY_ERR;
2075 }
2077 nsRefPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aID);
2078 return content ? CallQueryInterface(content, aResult) : NS_OK;
2079 }
2081 NS_IMETHODIMP
2082 nsDOMWindowUtils::GetViewId(nsIDOMElement* aElement, nsViewID* aResult)
2083 {
2084 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
2085 if (content && nsLayoutUtils::FindIDFor(content, aResult)) {
2086 return NS_OK;
2087 }
2088 return NS_ERROR_NOT_AVAILABLE;
2089 }
2091 NS_IMETHODIMP
2092 nsDOMWindowUtils::GetScreenPixelsPerCSSPixel(float* aScreenPixels)
2093 {
2094 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2095 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
2096 return window->GetDevicePixelRatio(aScreenPixels);
2097 }
2099 NS_IMETHODIMP
2100 nsDOMWindowUtils::GetFullZoom(float* aFullZoom)
2101 {
2102 *aFullZoom = 1.0f;
2104 if (!nsContentUtils::IsCallerChrome()) {
2105 return NS_ERROR_DOM_SECURITY_ERR;
2106 }
2108 nsPresContext* presContext = GetPresContext();
2109 if (!presContext) {
2110 return NS_OK;
2111 }
2113 *aFullZoom = presContext->DeviceContext()->GetPixelScale();
2115 return NS_OK;
2116 }
2118 NS_IMETHODIMP
2119 nsDOMWindowUtils::DispatchDOMEventViaPresShell(nsIDOMNode* aTarget,
2120 nsIDOMEvent* aEvent,
2121 bool aTrusted,
2122 bool* aRetVal)
2123 {
2124 if (!nsContentUtils::IsCallerChrome()) {
2125 return NS_ERROR_DOM_SECURITY_ERR;
2126 }
2128 NS_ENSURE_STATE(aEvent);
2129 aEvent->SetTrusted(aTrusted);
2130 WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
2131 NS_ENSURE_STATE(internalEvent);
2132 nsCOMPtr<nsIContent> content = do_QueryInterface(aTarget);
2133 NS_ENSURE_STATE(content);
2134 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2135 if (content->OwnerDoc()->GetWindow() != window) {
2136 return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
2137 }
2138 nsCOMPtr<nsIDocument> targetDoc = content->GetCurrentDoc();
2139 NS_ENSURE_STATE(targetDoc);
2140 nsRefPtr<nsIPresShell> targetShell = targetDoc->GetShell();
2141 NS_ENSURE_STATE(targetShell);
2143 targetDoc->FlushPendingNotifications(Flush_Layout);
2145 nsEventStatus status = nsEventStatus_eIgnore;
2146 targetShell->HandleEventWithTarget(internalEvent, nullptr, content, &status);
2147 *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
2148 return NS_OK;
2149 }
2151 static void
2152 InitEvent(WidgetGUIEvent& aEvent, LayoutDeviceIntPoint* aPt = nullptr)
2153 {
2154 if (aPt) {
2155 aEvent.refPoint = *aPt;
2156 }
2157 aEvent.time = PR_IntervalNow();
2158 }
2160 NS_IMETHODIMP
2161 nsDOMWindowUtils::SendCompositionEvent(const nsAString& aType,
2162 const nsAString& aData,
2163 const nsAString& aLocale)
2164 {
2165 if (!nsContentUtils::IsCallerChrome()) {
2166 return NS_ERROR_DOM_SECURITY_ERR;
2167 }
2169 // get the widget to send the event to
2170 nsCOMPtr<nsIWidget> widget = GetWidget();
2171 if (!widget) {
2172 return NS_ERROR_FAILURE;
2173 }
2175 uint32_t msg;
2176 if (aType.EqualsLiteral("compositionstart")) {
2177 msg = NS_COMPOSITION_START;
2178 } else if (aType.EqualsLiteral("compositionend")) {
2179 msg = NS_COMPOSITION_END;
2180 } else if (aType.EqualsLiteral("compositionupdate")) {
2181 msg = NS_COMPOSITION_UPDATE;
2182 } else {
2183 return NS_ERROR_FAILURE;
2184 }
2186 WidgetCompositionEvent compositionEvent(true, msg, widget);
2187 InitEvent(compositionEvent);
2188 if (msg != NS_COMPOSITION_START) {
2189 compositionEvent.data = aData;
2190 }
2192 compositionEvent.mFlags.mIsSynthesizedForTests = true;
2194 nsEventStatus status;
2195 nsresult rv = widget->DispatchEvent(&compositionEvent, status);
2196 NS_ENSURE_SUCCESS(rv, rv);
2198 return NS_OK;
2199 }
2201 NS_IMETHODIMP
2202 nsDOMWindowUtils::CreateCompositionStringSynthesizer(
2203 nsICompositionStringSynthesizer** aResult)
2204 {
2205 NS_ENSURE_ARG_POINTER(aResult);
2206 *aResult = nullptr;
2208 if (!nsContentUtils::IsCallerChrome()) {
2209 return NS_ERROR_DOM_SECURITY_ERR;
2210 }
2212 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2213 NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
2215 NS_ADDREF(*aResult = new CompositionStringSynthesizer(window));
2216 return NS_OK;
2217 }
2219 NS_IMETHODIMP
2220 nsDOMWindowUtils::SendQueryContentEvent(uint32_t aType,
2221 uint32_t aOffset, uint32_t aLength,
2222 int32_t aX, int32_t aY,
2223 uint32_t aAdditionalFlags,
2224 nsIQueryContentEventResult **aResult)
2225 {
2226 *aResult = nullptr;
2228 if (!nsContentUtils::IsCallerChrome()) {
2229 return NS_ERROR_DOM_SECURITY_ERR;
2230 }
2232 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2233 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
2235 nsIDocShell *docShell = window->GetDocShell();
2236 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
2238 nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
2239 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
2241 nsPresContext* presContext = presShell->GetPresContext();
2242 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
2244 // get the widget to send the event to
2245 nsCOMPtr<nsIWidget> widget = GetWidget();
2246 if (!widget) {
2247 return NS_ERROR_FAILURE;
2248 }
2250 if (aType != NS_QUERY_SELECTED_TEXT &&
2251 aType != NS_QUERY_TEXT_CONTENT &&
2252 aType != NS_QUERY_CARET_RECT &&
2253 aType != NS_QUERY_TEXT_RECT &&
2254 aType != NS_QUERY_EDITOR_RECT &&
2255 aType != NS_QUERY_CHARACTER_AT_POINT) {
2256 return NS_ERROR_INVALID_ARG;
2257 }
2259 nsCOMPtr<nsIWidget> targetWidget = widget;
2260 LayoutDeviceIntPoint pt(aX, aY);
2262 bool useNativeLineBreak =
2263 !(aAdditionalFlags & QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
2265 if (aType == QUERY_CHARACTER_AT_POINT) {
2266 // Looking for the widget at the point.
2267 WidgetQueryContentEvent dummyEvent(true, NS_QUERY_CONTENT_STATE, widget);
2268 dummyEvent.mUseNativeLineBreak = useNativeLineBreak;
2269 InitEvent(dummyEvent, &pt);
2270 nsIFrame* popupFrame =
2271 nsLayoutUtils::GetPopupFrameForEventCoordinates(presContext->GetRootPresContext(), &dummyEvent);
2273 nsIntRect widgetBounds;
2274 nsresult rv = widget->GetClientBounds(widgetBounds);
2275 NS_ENSURE_SUCCESS(rv, rv);
2276 widgetBounds.MoveTo(0, 0);
2278 // There is no popup frame at the point and the point isn't in our widget,
2279 // we cannot process this request.
2280 NS_ENSURE_TRUE(popupFrame ||
2281 widgetBounds.Contains(LayoutDeviceIntPoint::ToUntyped(pt)),
2282 NS_ERROR_FAILURE);
2284 // Fire the event on the widget at the point
2285 if (popupFrame) {
2286 targetWidget = popupFrame->GetNearestWidget();
2287 }
2288 }
2290 pt += LayoutDeviceIntPoint::FromUntyped(
2291 widget->WidgetToScreenOffset() - targetWidget->WidgetToScreenOffset());
2293 WidgetQueryContentEvent queryEvent(true, aType, targetWidget);
2294 InitEvent(queryEvent, &pt);
2296 switch (aType) {
2297 case NS_QUERY_TEXT_CONTENT:
2298 queryEvent.InitForQueryTextContent(aOffset, aLength, useNativeLineBreak);
2299 break;
2300 case NS_QUERY_CARET_RECT:
2301 queryEvent.InitForQueryCaretRect(aOffset, useNativeLineBreak);
2302 break;
2303 case NS_QUERY_TEXT_RECT:
2304 queryEvent.InitForQueryTextRect(aOffset, aLength, useNativeLineBreak);
2305 break;
2306 default:
2307 queryEvent.mUseNativeLineBreak = useNativeLineBreak;
2308 break;
2309 }
2311 nsEventStatus status;
2312 nsresult rv = targetWidget->DispatchEvent(&queryEvent, status);
2313 NS_ENSURE_SUCCESS(rv, rv);
2315 nsQueryContentEventResult* result = new nsQueryContentEventResult();
2316 NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
2317 result->SetEventResult(widget, queryEvent);
2318 NS_ADDREF(*aResult = result);
2319 return NS_OK;
2320 }
2322 NS_IMETHODIMP
2323 nsDOMWindowUtils::SendSelectionSetEvent(uint32_t aOffset,
2324 uint32_t aLength,
2325 uint32_t aAdditionalFlags,
2326 bool *aResult)
2327 {
2328 *aResult = false;
2330 if (!nsContentUtils::IsCallerChrome()) {
2331 return NS_ERROR_DOM_SECURITY_ERR;
2332 }
2334 // get the widget to send the event to
2335 nsCOMPtr<nsIWidget> widget = GetWidget();
2336 if (!widget) {
2337 return NS_ERROR_FAILURE;
2338 }
2340 WidgetSelectionEvent selectionEvent(true, NS_SELECTION_SET, widget);
2341 InitEvent(selectionEvent);
2343 selectionEvent.mOffset = aOffset;
2344 selectionEvent.mLength = aLength;
2345 selectionEvent.mReversed = (aAdditionalFlags & SELECTION_SET_FLAG_REVERSE);
2346 selectionEvent.mUseNativeLineBreak =
2347 !(aAdditionalFlags & SELECTION_SET_FLAG_USE_XP_LINE_BREAK);
2349 nsEventStatus status;
2350 nsresult rv = widget->DispatchEvent(&selectionEvent, status);
2351 NS_ENSURE_SUCCESS(rv, rv);
2353 *aResult = selectionEvent.mSucceeded;
2354 return NS_OK;
2355 }
2357 NS_IMETHODIMP
2358 nsDOMWindowUtils::SendContentCommandEvent(const nsAString& aType,
2359 nsITransferable * aTransferable)
2360 {
2361 if (!nsContentUtils::IsCallerChrome()) {
2362 return NS_ERROR_DOM_SECURITY_ERR;
2363 }
2365 // get the widget to send the event to
2366 nsCOMPtr<nsIWidget> widget = GetWidget();
2367 if (!widget)
2368 return NS_ERROR_FAILURE;
2370 int32_t msg;
2371 if (aType.EqualsLiteral("cut"))
2372 msg = NS_CONTENT_COMMAND_CUT;
2373 else if (aType.EqualsLiteral("copy"))
2374 msg = NS_CONTENT_COMMAND_COPY;
2375 else if (aType.EqualsLiteral("paste"))
2376 msg = NS_CONTENT_COMMAND_PASTE;
2377 else if (aType.EqualsLiteral("delete"))
2378 msg = NS_CONTENT_COMMAND_DELETE;
2379 else if (aType.EqualsLiteral("undo"))
2380 msg = NS_CONTENT_COMMAND_UNDO;
2381 else if (aType.EqualsLiteral("redo"))
2382 msg = NS_CONTENT_COMMAND_REDO;
2383 else if (aType.EqualsLiteral("pasteTransferable"))
2384 msg = NS_CONTENT_COMMAND_PASTE_TRANSFERABLE;
2385 else
2386 return NS_ERROR_FAILURE;
2388 WidgetContentCommandEvent event(true, msg, widget);
2389 if (msg == NS_CONTENT_COMMAND_PASTE_TRANSFERABLE) {
2390 event.mTransferable = aTransferable;
2391 }
2393 nsEventStatus status;
2394 return widget->DispatchEvent(&event, status);
2395 }
2397 NS_IMETHODIMP
2398 nsDOMWindowUtils::GetClassName(JS::Handle<JS::Value> aObject, JSContext* aCx,
2399 char** aName)
2400 {
2401 if (!nsContentUtils::IsCallerChrome()) {
2402 return NS_ERROR_DOM_SECURITY_ERR;
2403 }
2405 // Our argument must be a non-null object.
2406 if (JSVAL_IS_PRIMITIVE(aObject)) {
2407 return NS_ERROR_XPC_BAD_CONVERT_JS;
2408 }
2410 *aName = NS_strdup(JS_GetClass(JSVAL_TO_OBJECT(aObject))->name);
2411 NS_ABORT_IF_FALSE(*aName, "NS_strdup should be infallible.");
2412 return NS_OK;
2413 }
2415 NS_IMETHODIMP
2416 nsDOMWindowUtils::GetVisitedDependentComputedStyle(
2417 nsIDOMElement *aElement, const nsAString& aPseudoElement,
2418 const nsAString& aPropertyName, nsAString& aResult)
2419 {
2420 aResult.Truncate();
2422 if (!nsContentUtils::IsCallerChrome()) {
2423 return NS_ERROR_DOM_SECURITY_ERR;
2424 }
2426 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2427 NS_ENSURE_STATE(window);
2429 nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
2430 nsresult rv =
2431 window->GetComputedStyle(aElement, aPseudoElement, getter_AddRefs(decl));
2432 NS_ENSURE_SUCCESS(rv, rv);
2434 static_cast<nsComputedDOMStyle*>(decl.get())->SetExposeVisitedStyle(true);
2435 rv = decl->GetPropertyValue(aPropertyName, aResult);
2436 static_cast<nsComputedDOMStyle*>(decl.get())->SetExposeVisitedStyle(false);
2438 return rv;
2439 }
2441 NS_IMETHODIMP
2442 nsDOMWindowUtils::EnterModalState()
2443 {
2444 if (!nsContentUtils::IsCallerChrome()) {
2445 return NS_ERROR_DOM_SECURITY_ERR;
2446 }
2448 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2449 NS_ENSURE_STATE(window);
2451 window->EnterModalState();
2452 return NS_OK;
2453 }
2455 NS_IMETHODIMP
2456 nsDOMWindowUtils::LeaveModalState()
2457 {
2458 if (!nsContentUtils::IsCallerChrome()) {
2459 return NS_ERROR_DOM_SECURITY_ERR;
2460 }
2462 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2463 NS_ENSURE_STATE(window);
2465 window->LeaveModalState();
2466 return NS_OK;
2467 }
2469 NS_IMETHODIMP
2470 nsDOMWindowUtils::IsInModalState(bool *retval)
2471 {
2472 if (!nsContentUtils::IsCallerChrome()) {
2473 return NS_ERROR_DOM_SECURITY_ERR;
2474 }
2476 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2477 NS_ENSURE_STATE(window);
2479 *retval = static_cast<nsGlobalWindow*>(window.get())->IsInModalState();
2480 return NS_OK;
2481 }
2483 NS_IMETHODIMP
2484 nsDOMWindowUtils::GetParent(JS::Handle<JS::Value> aObject,
2485 JSContext* aCx,
2486 JS::MutableHandle<JS::Value> aParent)
2487 {
2488 if (!nsContentUtils::IsCallerChrome()) {
2489 return NS_ERROR_DOM_SECURITY_ERR;
2490 }
2492 // First argument must be an object.
2493 if (aObject.isPrimitive()) {
2494 return NS_ERROR_XPC_BAD_CONVERT_JS;
2495 }
2497 JS::Rooted<JSObject*> parent(aCx, JS_GetParent(&aObject.toObject()));
2499 // Outerize if necessary.
2500 if (parent) {
2501 if (JSObjectOp outerize = js::GetObjectClass(parent)->ext.outerObject) {
2502 parent = outerize(aCx, parent);
2503 }
2504 }
2506 aParent.setObject(*parent);
2507 return NS_OK;
2508 }
2510 NS_IMETHODIMP
2511 nsDOMWindowUtils::GetOuterWindowID(uint64_t *aWindowID)
2512 {
2513 if (!nsContentUtils::IsCallerChrome()) {
2514 return NS_ERROR_DOM_SECURITY_ERR;
2515 }
2517 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2518 NS_ENSURE_STATE(window);
2520 NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
2521 *aWindowID = window->WindowID();
2522 return NS_OK;
2523 }
2525 NS_IMETHODIMP
2526 nsDOMWindowUtils::GetCurrentInnerWindowID(uint64_t *aWindowID)
2527 {
2528 if (!nsContentUtils::IsCallerChrome()) {
2529 return NS_ERROR_DOM_SECURITY_ERR;
2530 }
2532 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2533 NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
2535 NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
2536 nsGlobalWindow* inner =
2537 static_cast<nsGlobalWindow*>(window.get())->GetCurrentInnerWindowInternal();
2538 if (!inner) {
2539 return NS_ERROR_NOT_AVAILABLE;
2540 }
2541 *aWindowID = inner->WindowID();
2542 return NS_OK;
2543 }
2545 NS_IMETHODIMP
2546 nsDOMWindowUtils::SuspendTimeouts()
2547 {
2548 if (!nsContentUtils::IsCallerChrome()) {
2549 return NS_ERROR_DOM_SECURITY_ERR;
2550 }
2552 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2553 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
2555 window->SuspendTimeouts();
2557 return NS_OK;
2558 }
2560 NS_IMETHODIMP
2561 nsDOMWindowUtils::ResumeTimeouts()
2562 {
2563 if (!nsContentUtils::IsCallerChrome()) {
2564 return NS_ERROR_DOM_SECURITY_ERR;
2565 }
2567 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2568 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
2570 window->ResumeTimeouts();
2572 return NS_OK;
2573 }
2575 NS_IMETHODIMP
2576 nsDOMWindowUtils::GetLayerManagerType(nsAString& aType)
2577 {
2578 if (!nsContentUtils::IsCallerChrome()) {
2579 return NS_ERROR_DOM_SECURITY_ERR;
2580 }
2582 nsCOMPtr<nsIWidget> widget = GetWidget();
2583 if (!widget)
2584 return NS_ERROR_FAILURE;
2586 LayerManager *mgr = widget->GetLayerManager(nsIWidget::LAYER_MANAGER_PERSISTENT);
2587 if (!mgr)
2588 return NS_ERROR_FAILURE;
2590 mgr->GetBackendName(aType);
2592 return NS_OK;
2593 }
2595 NS_IMETHODIMP
2596 nsDOMWindowUtils::GetLayerManagerRemote(bool* retval)
2597 {
2598 if (!nsContentUtils::IsCallerChrome()) {
2599 return NS_ERROR_DOM_SECURITY_ERR;
2600 }
2602 nsCOMPtr<nsIWidget> widget = GetWidget();
2603 if (!widget)
2604 return NS_ERROR_FAILURE;
2606 LayerManager *mgr = widget->GetLayerManager();
2607 if (!mgr)
2608 return NS_ERROR_FAILURE;
2610 *retval = !!mgr->AsShadowForwarder();
2611 return NS_OK;
2612 }
2614 NS_IMETHODIMP
2615 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
2616 {
2617 if (!nsContentUtils::IsCallerChrome()) {
2618 return NS_ERROR_DOM_SECURITY_ERR;
2619 }
2621 NS_ENSURE_ARG_POINTER(startIndex);
2623 nsCOMPtr<nsIWidget> widget = GetWidget();
2624 if (!widget)
2625 return NS_ERROR_FAILURE;
2627 LayerManager *mgr = widget->GetLayerManager();
2628 if (!mgr)
2629 return NS_ERROR_FAILURE;
2631 const uint32_t kRecordingMinSize = 60 * 10; // 10 seconds @60 fps.
2632 const uint32_t kRecordingMaxSize = 60 * 60 * 60; // One hour
2633 uint32_t bufferSize = Preferences::GetUint("toolkit.framesRecording.bufferSize", uint32_t(0));
2634 bufferSize = std::min(bufferSize, kRecordingMaxSize);
2635 bufferSize = std::max(bufferSize, kRecordingMinSize);
2636 *startIndex = mgr->StartFrameTimeRecording(bufferSize);
2638 return NS_OK;
2639 }
2641 NS_IMETHODIMP
2642 nsDOMWindowUtils::StopFrameTimeRecording(uint32_t startIndex,
2643 uint32_t *frameCount,
2644 float **frameIntervals)
2645 {
2646 if (!nsContentUtils::IsCallerChrome()) {
2647 return NS_ERROR_DOM_SECURITY_ERR;
2648 }
2650 NS_ENSURE_ARG_POINTER(frameCount);
2651 NS_ENSURE_ARG_POINTER(frameIntervals);
2653 nsCOMPtr<nsIWidget> widget = GetWidget();
2654 if (!widget)
2655 return NS_ERROR_FAILURE;
2657 LayerManager *mgr = widget->GetLayerManager();
2658 if (!mgr)
2659 return NS_ERROR_FAILURE;
2661 nsTArray<float> tmpFrameIntervals;
2662 mgr->StopFrameTimeRecording(startIndex, tmpFrameIntervals);
2663 *frameCount = tmpFrameIntervals.Length();
2665 *frameIntervals = (float*)nsMemory::Alloc(*frameCount * sizeof(float));
2667 /* copy over the frame intervals and paint times into the arrays we just allocated */
2668 for (uint32_t i = 0; i < *frameCount; i++) {
2669 (*frameIntervals)[i] = tmpFrameIntervals[i];
2670 }
2672 return NS_OK;
2673 }
2675 NS_IMETHODIMP
2676 nsDOMWindowUtils::BeginTabSwitch()
2677 {
2678 if (!nsContentUtils::IsCallerChrome()) {
2679 return NS_ERROR_DOM_SECURITY_ERR;
2680 }
2682 nsCOMPtr<nsIWidget> widget = GetWidget();
2683 if (!widget)
2684 return NS_ERROR_FAILURE;
2686 LayerManager *mgr = widget->GetLayerManager();
2687 if (!mgr)
2688 return NS_ERROR_FAILURE;
2690 mgr->BeginTabSwitch();
2692 return NS_OK;
2693 }
2695 static bool
2696 ComputeAnimationValue(nsCSSProperty aProperty,
2697 Element* aElement,
2698 const nsAString& aInput,
2699 nsStyleAnimation::Value& aOutput)
2700 {
2702 if (!nsStyleAnimation::ComputeValue(aProperty, aElement, aInput,
2703 false, aOutput)) {
2704 return false;
2705 }
2707 // This matches TransExtractComputedValue in nsTransitionManager.cpp.
2708 if (aProperty == eCSSProperty_visibility) {
2709 NS_ABORT_IF_FALSE(aOutput.GetUnit() == nsStyleAnimation::eUnit_Enumerated,
2710 "unexpected unit");
2711 aOutput.SetIntValue(aOutput.GetIntValue(),
2712 nsStyleAnimation::eUnit_Visibility);
2713 }
2715 return true;
2716 }
2718 NS_IMETHODIMP
2719 nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
2720 {
2721 if (!nsContentUtils::IsCallerChrome()) {
2722 return NS_ERROR_DOM_SECURITY_ERR;
2723 }
2725 nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
2726 driver->AdvanceTimeAndRefresh(aMilliseconds);
2728 LayerTransactionChild* transaction = GetLayerTransaction();
2729 if (transaction) {
2730 transaction->SendSetTestSampleTime(driver->MostRecentRefresh());
2731 }
2733 return NS_OK;
2734 }
2736 NS_IMETHODIMP
2737 nsDOMWindowUtils::RestoreNormalRefresh()
2738 {
2739 if (!nsContentUtils::IsCallerChrome()) {
2740 return NS_ERROR_DOM_SECURITY_ERR;
2741 }
2743 // Kick the compositor out of test mode before the refresh driver, so that
2744 // the refresh driver doesn't send an update that gets ignored by the
2745 // compositor.
2746 LayerTransactionChild* transaction = GetLayerTransaction();
2747 if (transaction) {
2748 transaction->SendLeaveTestMode();
2749 }
2751 nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
2752 driver->RestoreNormalRefresh();
2754 return NS_OK;
2755 }
2757 NS_IMETHODIMP
2758 nsDOMWindowUtils::GetIsTestControllingRefreshes(bool *aResult)
2759 {
2760 if (!nsContentUtils::IsCallerChrome()) {
2761 return NS_ERROR_DOM_SECURITY_ERR;
2762 }
2764 nsPresContext* pc = GetPresContext();
2765 *aResult =
2766 pc ? pc->RefreshDriver()->IsTestControllingRefreshesEnabled() : false;
2768 return NS_OK;
2769 }
2771 NS_IMETHODIMP
2772 nsDOMWindowUtils::SetAsyncScrollOffset(nsIDOMNode* aNode,
2773 int32_t aX, int32_t aY)
2774 {
2775 nsCOMPtr<Element> element = do_QueryInterface(aNode);
2776 if (!element) {
2777 return NS_ERROR_INVALID_ARG;
2778 }
2779 nsIFrame* frame = element->GetPrimaryFrame();
2780 if (!frame) {
2781 return NS_ERROR_UNEXPECTED;
2782 }
2783 nsIScrollableFrame* scrollable = do_QueryFrame(frame);
2784 nsPresContext* presContext = frame->PresContext();
2785 nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
2786 if (!scrollable) {
2787 if (rootScrollFrame && rootScrollFrame->GetContent() == element) {
2788 frame = rootScrollFrame;
2789 scrollable = do_QueryFrame(frame);
2790 }
2791 }
2792 if (!scrollable) {
2793 return NS_ERROR_UNEXPECTED;
2794 }
2795 Layer* layer = FrameLayerBuilder::GetDedicatedLayer(scrollable->GetScrolledFrame(),
2796 nsDisplayItem::TYPE_SCROLL_LAYER);
2797 if (!layer) {
2798 if (rootScrollFrame == frame && !presContext->GetParentPresContext()) {
2799 nsIWidget* widget = GetWidget();
2800 if (widget) {
2801 LayerManager* manager = widget->GetLayerManager();
2802 if (manager) {
2803 layer = manager->GetRoot();
2804 }
2805 }
2806 }
2807 if (!layer) {
2808 return NS_ERROR_UNEXPECTED;
2809 }
2810 }
2811 ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
2812 if (!forwarder || !forwarder->HasShadowManager()) {
2813 return NS_ERROR_UNEXPECTED;
2814 }
2815 forwarder->GetShadowManager()->SendSetAsyncScrollOffset(
2816 layer->AsShadowableLayer()->GetShadow(), aX, aY);
2817 return NS_OK;
2818 }
2820 NS_IMETHODIMP
2821 nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
2822 const nsAString& aProperty,
2823 const nsAString& aValue1,
2824 const nsAString& aValue2,
2825 double* aResult)
2826 {
2827 if (!nsContentUtils::IsCallerChrome()) {
2828 return NS_ERROR_DOM_SECURITY_ERR;
2829 }
2831 nsresult rv;
2832 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
2833 NS_ENSURE_SUCCESS(rv, rv);
2835 // Convert direction-dependent properties as appropriate, e.g.,
2836 // border-left to border-left-value.
2837 nsCSSProperty property =
2838 nsCSSProps::LookupProperty(aProperty, nsCSSProps::eIgnoreEnabledState);
2839 if (property != eCSSProperty_UNKNOWN && nsCSSProps::IsShorthand(property)) {
2840 nsCSSProperty subprop0 = *nsCSSProps::SubpropertyEntryFor(property);
2841 if (nsCSSProps::PropHasFlags(subprop0, CSS_PROPERTY_REPORT_OTHER_NAME) &&
2842 nsCSSProps::OtherNameFor(subprop0) == property) {
2843 property = subprop0;
2844 } else {
2845 property = eCSSProperty_UNKNOWN;
2846 }
2847 }
2849 NS_ABORT_IF_FALSE(property == eCSSProperty_UNKNOWN ||
2850 !nsCSSProps::IsShorthand(property),
2851 "should not have shorthand");
2853 nsStyleAnimation::Value v1, v2;
2854 if (property == eCSSProperty_UNKNOWN ||
2855 !ComputeAnimationValue(property, content->AsElement(), aValue1, v1) ||
2856 !ComputeAnimationValue(property, content->AsElement(), aValue2, v2)) {
2857 return NS_ERROR_ILLEGAL_VALUE;
2858 }
2860 if (!nsStyleAnimation::ComputeDistance(property, v1, v2, *aResult)) {
2861 return NS_ERROR_FAILURE;
2862 }
2864 return NS_OK;
2865 }
2867 nsresult
2868 nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
2869 uint32_t aFlags,
2870 nscolor aBackgroundColor,
2871 gfxContext* aThebesContext)
2872 {
2873 if (!nsContentUtils::IsCallerChrome()) {
2874 return NS_ERROR_DOM_SECURITY_ERR;
2875 }
2877 nsCOMPtr<nsIDocument> doc = GetDocument();
2878 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
2880 // Get Primary Shell
2881 nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
2882 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
2884 // Render Document
2885 return presShell->RenderDocument(aRect, aFlags, aBackgroundColor, aThebesContext);
2886 }
2888 NS_IMETHODIMP
2889 nsDOMWindowUtils::GetCursorType(int16_t *aCursor)
2890 {
2891 if (!nsContentUtils::IsCallerChrome()) {
2892 return NS_ERROR_DOM_SECURITY_ERR;
2893 }
2895 NS_ENSURE_ARG_POINTER(aCursor);
2897 nsIDocument* doc = GetDocument();
2898 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
2900 bool isSameDoc = false;
2901 do {
2902 if (EventStateManager::sMouseOverDocument == doc) {
2903 isSameDoc = true;
2904 break;
2905 }
2906 } while ((doc = doc->GetParentDocument()));
2908 if (!isSameDoc) {
2909 *aCursor = eCursor_none;
2910 return NS_OK;
2911 }
2913 nsCOMPtr<nsIWidget> widget = GetWidget();
2914 if (!widget)
2915 return NS_ERROR_FAILURE;
2917 // fetch cursor value from window's widget
2918 *aCursor = widget->GetCursor();
2920 return NS_OK;
2921 }
2923 NS_IMETHODIMP
2924 nsDOMWindowUtils::GetDisplayDPI(float *aDPI)
2925 {
2926 if (!nsContentUtils::IsCallerChrome()) {
2927 return NS_ERROR_DOM_SECURITY_ERR;
2928 }
2930 nsCOMPtr<nsIWidget> widget = GetWidget();
2931 if (!widget)
2932 return NS_ERROR_FAILURE;
2934 *aDPI = widget->GetDPI();
2936 return NS_OK;
2937 }
2940 NS_IMETHODIMP
2941 nsDOMWindowUtils::GetOuterWindowWithId(uint64_t aWindowID,
2942 nsIDOMWindow** aWindow)
2943 {
2944 if (!nsContentUtils::IsCallerChrome()) {
2945 return NS_ERROR_DOM_SECURITY_ERR;
2946 }
2948 // XXX This method is deprecated. See bug 865664.
2949 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
2950 NS_LITERAL_CSTRING("DOM"),
2951 nsContentUtils::GetDocumentFromCaller(),
2952 nsContentUtils::eDOM_PROPERTIES,
2953 "GetWindowWithOuterIdWarning");
2955 *aWindow = nsGlobalWindow::GetOuterWindowWithId(aWindowID);
2956 NS_IF_ADDREF(*aWindow);
2957 return NS_OK;
2958 }
2960 NS_IMETHODIMP
2961 nsDOMWindowUtils::GetContainerElement(nsIDOMElement** aResult)
2962 {
2963 if (!nsContentUtils::IsCallerChrome()) {
2964 return NS_ERROR_DOM_SECURITY_ERR;
2965 }
2967 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
2968 NS_ENSURE_STATE(window);
2970 nsCOMPtr<nsIDOMElement> element =
2971 do_QueryInterface(window->GetFrameElementInternal());
2973 element.forget(aResult);
2974 return NS_OK;
2975 }
2977 NS_IMETHODIMP
2978 nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
2979 nsIDOMFile **aDOMFile)
2980 {
2981 if (!nsContentUtils::IsCallerChrome()) {
2982 return NS_ERROR_DOM_SECURITY_ERR;
2983 }
2985 if (!aFile) {
2986 return NS_ERROR_FAILURE;
2987 }
2989 NS_ADDREF(*aDOMFile = new nsDOMFileFile(aFile));
2990 return NS_OK;
2991 }
2993 #ifdef DEBUG
2994 static bool
2995 CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
2996 {
2997 gfx::Matrix transform;
2998 if (!aLayer->GetTransform().Is2D(&transform) ||
2999 transform.HasNonIntegerTranslation())
3000 return false;
3001 transform.NudgeToIntegers();
3002 nsIntPoint offset = aOffset + nsIntPoint(transform._31, transform._32);
3004 Layer* child = aLayer->GetFirstChild();
3005 if (child) {
3006 while (child) {
3007 if (!CheckLeafLayers(child, offset, aCoveredRegion))
3008 return false;
3009 child = child->GetNextSibling();
3010 }
3011 } else {
3012 nsIntRegion rgn = aLayer->GetVisibleRegion();
3013 rgn.MoveBy(offset);
3014 nsIntRegion tmp;
3015 tmp.And(rgn, *aCoveredRegion);
3016 if (!tmp.IsEmpty())
3017 return false;
3018 aCoveredRegion->Or(*aCoveredRegion, rgn);
3019 }
3021 return true;
3022 }
3023 #endif
3025 NS_IMETHODIMP
3026 nsDOMWindowUtils::LeafLayersPartitionWindow(bool* aResult)
3027 {
3028 if (!nsContentUtils::IsCallerChrome()) {
3029 return NS_ERROR_DOM_SECURITY_ERR;
3030 }
3032 *aResult = true;
3033 #ifdef DEBUG
3034 nsIWidget* widget = GetWidget();
3035 if (!widget)
3036 return NS_ERROR_FAILURE;
3037 LayerManager* manager = widget->GetLayerManager();
3038 if (!manager)
3039 return NS_ERROR_FAILURE;
3040 nsPresContext* presContext = GetPresContext();
3041 if (!presContext)
3042 return NS_ERROR_FAILURE;
3043 Layer* root = manager->GetRoot();
3044 if (!root)
3045 return NS_ERROR_FAILURE;
3047 nsIntPoint offset(0, 0);
3048 nsIntRegion coveredRegion;
3049 if (!CheckLeafLayers(root, offset, &coveredRegion)) {
3050 *aResult = false;
3051 }
3052 if (!coveredRegion.IsEqual(root->GetVisibleRegion())) {
3053 *aResult = false;
3054 }
3055 #endif
3056 return NS_OK;
3057 }
3059 NS_IMETHODIMP
3060 nsDOMWindowUtils::GetMayHaveTouchEventListeners(bool* aResult)
3061 {
3062 if (!nsContentUtils::IsCallerChrome()) {
3063 return NS_ERROR_DOM_SECURITY_ERR;
3064 }
3066 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3067 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
3069 nsPIDOMWindow* innerWindow = window->GetCurrentInnerWindow();
3070 *aResult = innerWindow ? innerWindow->HasTouchEventListeners() : false;
3071 return NS_OK;
3072 }
3074 NS_IMETHODIMP
3075 nsDOMWindowUtils::CheckAndClearPaintedState(nsIDOMElement* aElement, bool* aResult)
3076 {
3077 if (!nsContentUtils::IsCallerChrome()) {
3078 return NS_ERROR_DOM_SECURITY_ERR;
3079 }
3081 if (!aElement) {
3082 return NS_ERROR_INVALID_ARG;
3083 }
3085 nsresult rv;
3086 nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
3087 NS_ENSURE_SUCCESS(rv, rv);
3089 nsIFrame* frame = content->GetPrimaryFrame();
3091 if (!frame) {
3092 *aResult = false;
3093 return NS_OK;
3094 }
3096 *aResult = frame->CheckAndClearPaintedState();
3097 return NS_OK;
3098 }
3100 NS_IMETHODIMP
3101 nsDOMWindowUtils::EnableDialogs()
3102 {
3103 if (!nsContentUtils::IsCallerChrome()) {
3104 return NS_ERROR_DOM_SECURITY_ERR;
3105 }
3107 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3108 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
3110 static_cast<nsGlobalWindow*>(window.get())->EnableDialogs();
3111 return NS_OK;
3112 }
3114 NS_IMETHODIMP
3115 nsDOMWindowUtils::DisableDialogs()
3116 {
3117 if (!nsContentUtils::IsCallerChrome()) {
3118 return NS_ERROR_DOM_SECURITY_ERR;
3119 }
3121 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3122 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
3124 static_cast<nsGlobalWindow*>(window.get())->DisableDialogs();
3125 return NS_OK;
3126 }
3128 NS_IMETHODIMP
3129 nsDOMWindowUtils::AreDialogsEnabled(bool* aResult)
3130 {
3131 if (!nsContentUtils::IsCallerChrome()) {
3132 return NS_ERROR_DOM_SECURITY_ERR;
3133 }
3135 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3136 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
3138 *aResult = static_cast<nsGlobalWindow*>(window.get())->AreDialogsEnabled();
3139 return NS_OK;
3140 }
3142 static nsIDOMBlob*
3143 GetXPConnectNative(JSContext* aCx, JSObject* aObj) {
3144 nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
3145 nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj));
3146 return blob;
3147 }
3149 static nsresult
3150 GetFileOrBlob(const nsAString& aName, JS::Handle<JS::Value> aBlobParts,
3151 JS::Handle<JS::Value> aParameters, JSContext* aCx,
3152 uint8_t aOptionalArgCount, nsISupports** aResult)
3153 {
3154 if (!nsContentUtils::IsCallerChrome()) {
3155 return NS_ERROR_DOM_SECURITY_ERR;
3156 }
3158 nsresult rv;
3160 nsCOMPtr<nsISupports> file;
3162 if (aName.IsVoid()) {
3163 rv = nsDOMMultipartFile::NewBlob(getter_AddRefs(file));
3164 }
3165 else {
3166 rv = nsDOMMultipartFile::NewFile(aName, getter_AddRefs(file));
3167 }
3168 NS_ENSURE_SUCCESS(rv, rv);
3170 nsDOMMultipartFile* domFile =
3171 static_cast<nsDOMMultipartFile*>(static_cast<nsIDOMFile*>(file.get()));
3173 JS::AutoValueArray<2> args(aCx);
3174 args[0].set(aBlobParts);
3175 args[1].set(aParameters);
3177 rv = domFile->InitBlob(aCx, aOptionalArgCount, args.begin(), GetXPConnectNative);
3178 NS_ENSURE_SUCCESS(rv, rv);
3180 file.forget(aResult);
3181 return NS_OK;
3182 }
3184 NS_IMETHODIMP
3185 nsDOMWindowUtils::GetFile(const nsAString& aName, JS::Handle<JS::Value> aBlobParts,
3186 JS::Handle<JS::Value> aParameters, JSContext* aCx,
3187 uint8_t aOptionalArgCount, nsIDOMFile** aResult)
3188 {
3189 if (!nsContentUtils::IsCallerChrome()) {
3190 return NS_ERROR_DOM_SECURITY_ERR;
3191 }
3193 nsCOMPtr<nsISupports> file;
3194 nsresult rv = GetFileOrBlob(aName, aBlobParts, aParameters, aCx,
3195 aOptionalArgCount, getter_AddRefs(file));
3196 NS_ENSURE_SUCCESS(rv, rv);
3198 nsCOMPtr<nsIDOMFile> result = do_QueryInterface(file);
3199 result.forget(aResult);
3201 return NS_OK;
3202 }
3204 NS_IMETHODIMP
3205 nsDOMWindowUtils::GetBlob(JS::Handle<JS::Value> aBlobParts,
3206 JS::Handle<JS::Value> aParameters, JSContext* aCx,
3207 uint8_t aOptionalArgCount, nsIDOMBlob** aResult)
3208 {
3209 if (!nsContentUtils::IsCallerChrome()) {
3210 return NS_ERROR_DOM_SECURITY_ERR;
3211 }
3213 nsCOMPtr<nsISupports> blob;
3214 nsresult rv = GetFileOrBlob(NullString(), aBlobParts, aParameters, aCx,
3215 aOptionalArgCount, getter_AddRefs(blob));
3216 NS_ENSURE_SUCCESS(rv, rv);
3218 nsCOMPtr<nsIDOMBlob> result = do_QueryInterface(blob);
3219 result.forget(aResult);
3221 return NS_OK;
3222 }
3224 NS_IMETHODIMP
3225 nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
3226 int64_t* aResult)
3227 {
3228 if (!nsContentUtils::IsCallerChrome()) {
3229 return NS_ERROR_DOM_SECURITY_ERR;
3230 }
3232 if (!JSVAL_IS_PRIMITIVE(aFile)) {
3233 JSObject* obj = JSVAL_TO_OBJECT(aFile);
3235 file::FileHandle* fileHandle;
3236 if (NS_SUCCEEDED(UNWRAP_OBJECT(FileHandle, obj, fileHandle))) {
3237 *aResult = fileHandle->GetFileId();
3238 return NS_OK;
3239 }
3241 nsISupports* nativeObj =
3242 nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
3244 nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(nativeObj);
3245 if (blob) {
3246 *aResult = blob->GetFileId();
3247 return NS_OK;
3248 }
3249 }
3251 *aResult = -1;
3252 return NS_OK;
3253 }
3255 NS_IMETHODIMP
3256 nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
3257 JS::Handle<JS::Value> aOptions,
3258 int32_t* aRefCnt, int32_t* aDBRefCnt,
3259 int32_t* aSliceRefCnt, JSContext* aCx,
3260 bool* aResult)
3261 {
3262 if (!nsContentUtils::IsCallerChrome()) {
3263 return NS_ERROR_DOM_SECURITY_ERR;
3264 }
3266 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3267 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
3269 nsCString origin;
3270 quota::PersistenceType defaultPersistenceType;
3271 nsresult rv =
3272 quota::QuotaManager::GetInfoFromWindow(window, nullptr, &origin, nullptr,
3273 &defaultPersistenceType);
3274 NS_ENSURE_SUCCESS(rv, rv);
3276 IDBOpenDBOptions options;
3277 JS::Rooted<JS::Value> optionsVal(aCx, aOptions);
3278 if (!options.Init(aCx, optionsVal)) {
3279 return NS_ERROR_TYPE_ERR;
3280 }
3282 quota::PersistenceType persistenceType =
3283 quota::PersistenceTypeFromStorage(options.mStorage, defaultPersistenceType);
3285 nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
3286 indexedDB::IndexedDatabaseManager::Get();
3288 if (mgr) {
3289 rv = mgr->BlockAndGetFileReferences(persistenceType, origin, aDatabaseName,
3290 aId, aRefCnt, aDBRefCnt, aSliceRefCnt,
3291 aResult);
3292 NS_ENSURE_SUCCESS(rv, rv);
3293 }
3294 else {
3295 *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
3296 *aResult = false;
3297 }
3299 return NS_OK;
3300 }
3302 NS_IMETHODIMP
3303 nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
3304 {
3305 if (!nsContentUtils::IsCallerChrome()) {
3306 return NS_ERROR_DOM_SECURITY_ERR;
3307 }
3309 *aResult = JS::IsIncrementalGCEnabled(JS_GetRuntime(cx));
3310 return NS_OK;
3311 }
3313 NS_IMETHODIMP
3314 nsDOMWindowUtils::StartPCCountProfiling(JSContext* cx)
3315 {
3316 if (!nsContentUtils::IsCallerChrome()) {
3317 return NS_ERROR_DOM_SECURITY_ERR;
3318 }
3320 js::StartPCCountProfiling(cx);
3321 return NS_OK;
3322 }
3324 NS_IMETHODIMP
3325 nsDOMWindowUtils::StopPCCountProfiling(JSContext* cx)
3326 {
3327 if (!nsContentUtils::IsCallerChrome()) {
3328 return NS_ERROR_DOM_SECURITY_ERR;
3329 }
3331 js::StopPCCountProfiling(cx);
3332 return NS_OK;
3333 }
3335 NS_IMETHODIMP
3336 nsDOMWindowUtils::PurgePCCounts(JSContext* cx)
3337 {
3338 if (!nsContentUtils::IsCallerChrome()) {
3339 return NS_ERROR_DOM_SECURITY_ERR;
3340 }
3342 js::PurgePCCounts(cx);
3343 return NS_OK;
3344 }
3346 NS_IMETHODIMP
3347 nsDOMWindowUtils::GetPCCountScriptCount(JSContext* cx, int32_t *result)
3348 {
3349 if (!nsContentUtils::IsCallerChrome()) {
3350 return NS_ERROR_DOM_SECURITY_ERR;
3351 }
3353 *result = js::GetPCCountScriptCount(cx);
3354 return NS_OK;
3355 }
3357 NS_IMETHODIMP
3358 nsDOMWindowUtils::GetPCCountScriptSummary(int32_t script, JSContext* cx, nsAString& result)
3359 {
3360 if (!nsContentUtils::IsCallerChrome()) {
3361 return NS_ERROR_DOM_SECURITY_ERR;
3362 }
3364 JSString *text = js::GetPCCountScriptSummary(cx, script);
3365 if (!text)
3366 return NS_ERROR_FAILURE;
3368 nsDependentJSString str;
3369 if (!str.init(cx, text))
3370 return NS_ERROR_FAILURE;
3372 result = str;
3373 return NS_OK;
3374 }
3376 NS_IMETHODIMP
3377 nsDOMWindowUtils::GetPCCountScriptContents(int32_t script, JSContext* cx, nsAString& result)
3378 {
3379 if (!nsContentUtils::IsCallerChrome()) {
3380 return NS_ERROR_DOM_SECURITY_ERR;
3381 }
3383 JSString *text = js::GetPCCountScriptContents(cx, script);
3384 if (!text)
3385 return NS_ERROR_FAILURE;
3387 nsDependentJSString str;
3388 if (!str.init(cx, text))
3389 return NS_ERROR_FAILURE;
3391 result = str;
3392 return NS_OK;
3393 }
3395 NS_IMETHODIMP
3396 nsDOMWindowUtils::GetPaintingSuppressed(bool *aPaintingSuppressed)
3397 {
3398 if (!nsContentUtils::IsCallerChrome()) {
3399 return NS_ERROR_DOM_SECURITY_ERR;
3400 }
3402 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3403 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
3404 nsIDocShell *docShell = window->GetDocShell();
3405 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
3407 nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
3408 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
3410 *aPaintingSuppressed = presShell->IsPaintingSuppressed();
3411 return NS_OK;
3412 }
3414 NS_IMETHODIMP
3415 nsDOMWindowUtils::GetPlugins(JSContext* cx, JS::MutableHandle<JS::Value> aPlugins)
3416 {
3417 if (!nsContentUtils::IsCallerChrome()) {
3418 return NS_ERROR_DOM_SECURITY_ERR;
3419 }
3421 nsCOMPtr<nsIDocument> doc = GetDocument();
3422 NS_ENSURE_STATE(doc);
3424 nsTArray<nsIObjectLoadingContent*> plugins;
3425 doc->GetPlugins(plugins);
3427 JS::Rooted<JSObject*> jsPlugins(cx);
3428 nsresult rv = nsTArrayToJSArray(cx, plugins, jsPlugins.address());
3429 NS_ENSURE_SUCCESS(rv, rv);
3431 aPlugins.setObject(*jsPlugins);
3432 return NS_OK;
3433 }
3435 static void
3436 MaybeReflowForInflationScreenWidthChange(nsPresContext *aPresContext)
3437 {
3438 if (aPresContext) {
3439 nsIPresShell* presShell = aPresContext->GetPresShell();
3440 bool fontInflationWasEnabled = presShell->FontSizeInflationEnabled();
3441 presShell->NotifyFontSizeInflationEnabledIsDirty();
3442 bool changed = false;
3443 if (presShell && presShell->FontSizeInflationEnabled() &&
3444 presShell->FontSizeInflationMinTwips() != 0) {
3445 aPresContext->ScreenWidthInchesForFontInflation(&changed);
3446 }
3448 changed = changed ||
3449 (fontInflationWasEnabled != presShell->FontSizeInflationEnabled());
3450 if (changed) {
3451 nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
3452 if (docShell) {
3453 nsCOMPtr<nsIContentViewer> cv;
3454 docShell->GetContentViewer(getter_AddRefs(cv));
3455 nsCOMPtr<nsIMarkupDocumentViewer> mudv = do_QueryInterface(cv);
3456 if (mudv) {
3457 nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> > array;
3458 mudv->AppendSubtree(array);
3459 for (uint32_t i = 0, iEnd = array.Length(); i < iEnd; ++i) {
3460 nsCOMPtr<nsIPresShell> shell;
3461 nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(array[i]);
3462 cv->GetPresShell(getter_AddRefs(shell));
3463 if (shell) {
3464 nsIFrame *rootFrame = shell->GetRootFrame();
3465 if (rootFrame) {
3466 shell->FrameNeedsReflow(rootFrame,
3467 nsIPresShell::eStyleChange,
3468 NS_FRAME_IS_DIRTY);
3469 }
3470 }
3471 }
3472 }
3473 }
3474 }
3475 }
3476 }
3478 NS_IMETHODIMP
3479 nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aHeight)
3480 {
3481 if (!nsContentUtils::IsCallerChrome()) {
3482 return NS_ERROR_DOM_SECURITY_ERR;
3483 }
3485 if (!(aWidth >= 0.0 && aHeight >= 0.0)) {
3486 return NS_ERROR_ILLEGAL_VALUE;
3487 }
3489 nsIPresShell* presShell = GetPresShell();
3490 if (!presShell) {
3491 return NS_ERROR_FAILURE;
3492 }
3494 presShell->SetScrollPositionClampingScrollPortSize(
3495 nsPresContext::CSSPixelsToAppUnits(aWidth),
3496 nsPresContext::CSSPixelsToAppUnits(aHeight));
3498 // When the "font.size.inflation.minTwips" preference is set, the
3499 // layout depends on the size of the screen. Since when the size
3500 // of the screen changes, the scroll position clamping scroll port
3501 // size also changes, we hook in the needed updates here rather
3502 // than adding a separate notification just for this change.
3503 nsPresContext* presContext = GetPresContext();
3504 MaybeReflowForInflationScreenWidthChange(presContext);
3506 return NS_OK;
3507 }
3509 NS_IMETHODIMP
3510 nsDOMWindowUtils::SetContentDocumentFixedPositionMargins(float aTop, float aRight,
3511 float aBottom, float aLeft)
3512 {
3513 if (!nsContentUtils::IsCallerChrome()) {
3514 return NS_ERROR_DOM_SECURITY_ERR;
3515 }
3517 if (!(aTop >= 0.0f && aRight >= 0.0f && aBottom >= 0.0f && aLeft >= 0.0f)) {
3518 return NS_ERROR_ILLEGAL_VALUE;
3519 }
3521 nsIPresShell* presShell = GetPresShell();
3522 if (!presShell) {
3523 return NS_ERROR_FAILURE;
3524 }
3526 nsMargin margins(nsPresContext::CSSPixelsToAppUnits(aTop),
3527 nsPresContext::CSSPixelsToAppUnits(aRight),
3528 nsPresContext::CSSPixelsToAppUnits(aBottom),
3529 nsPresContext::CSSPixelsToAppUnits(aLeft));
3530 presShell->SetContentDocumentFixedPositionMargins(margins);
3532 return NS_OK;
3533 }
3535 nsresult
3536 nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
3537 const nsAString& aNewOrigin)
3538 {
3539 if (!nsContentUtils::IsCallerChrome()) {
3540 return NS_ERROR_DOM_SECURITY_ERR;
3541 }
3543 nsCOMPtr<nsIDocument> doc = GetDocument();
3544 NS_ENSURE_STATE(doc);
3546 doc->RemoteFrameFullscreenChanged(aFrameElement, aNewOrigin);
3547 return NS_OK;
3548 }
3550 nsresult
3551 nsDOMWindowUtils::RemoteFrameFullscreenReverted()
3552 {
3553 if (!nsContentUtils::IsCallerChrome()) {
3554 return NS_ERROR_DOM_SECURITY_ERR;
3555 }
3557 nsCOMPtr<nsIDocument> doc = GetDocument();
3558 NS_ENSURE_STATE(doc);
3560 doc->RemoteFrameFullscreenReverted();
3561 return NS_OK;
3562 }
3564 nsresult
3565 nsDOMWindowUtils::ExitFullscreen()
3566 {
3567 if (!nsContentUtils::IsCallerChrome()) {
3568 return NS_ERROR_DOM_SECURITY_ERR;
3569 }
3571 nsIDocument::ExitFullscreen(nullptr, /* async */ false);
3572 return NS_OK;
3573 }
3575 NS_IMETHODIMP
3576 nsDOMWindowUtils::SelectAtPoint(float aX, float aY, uint32_t aSelectBehavior,
3577 bool *_retval)
3578 {
3579 *_retval = false;
3580 if (!nsContentUtils::IsCallerChrome()) {
3581 return NS_ERROR_DOM_SECURITY_ERR;
3582 }
3584 nsSelectionAmount amount;
3585 switch (aSelectBehavior) {
3586 case nsIDOMWindowUtils::SELECT_CHARACTER:
3587 amount = eSelectCharacter;
3588 break;
3589 case nsIDOMWindowUtils::SELECT_CLUSTER:
3590 amount = eSelectCluster;
3591 break;
3592 case nsIDOMWindowUtils::SELECT_WORD:
3593 amount = eSelectWord;
3594 break;
3595 case nsIDOMWindowUtils::SELECT_LINE:
3596 amount = eSelectLine;
3597 break;
3598 case nsIDOMWindowUtils::SELECT_BEGINLINE:
3599 amount = eSelectBeginLine;
3600 break;
3601 case nsIDOMWindowUtils::SELECT_ENDLINE:
3602 amount = eSelectEndLine;
3603 break;
3604 case nsIDOMWindowUtils::SELECT_PARAGRAPH:
3605 amount = eSelectParagraph;
3606 break;
3607 case nsIDOMWindowUtils::SELECT_WORDNOSPACE:
3608 amount = eSelectWordNoSpace;
3609 break;
3610 default:
3611 return NS_ERROR_INVALID_ARG;
3612 }
3614 nsIPresShell* presShell = GetPresShell();
3615 if (!presShell) {
3616 return NS_ERROR_UNEXPECTED;
3617 }
3619 // The root frame for this content window
3620 nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
3621 if (!rootFrame) {
3622 return NS_ERROR_UNEXPECTED;
3623 }
3625 // Get the target frame at the client coordinates passed to us
3626 nsPoint offset;
3627 nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
3628 nsIntPoint pt = LayoutDeviceIntPoint::ToUntyped(
3629 ToWidgetPoint(CSSPoint(aX, aY), offset, GetPresContext()));
3630 nsPoint ptInRoot =
3631 nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, pt, rootFrame);
3632 nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
3633 // This can happen if the page hasn't loaded yet or if the point
3634 // is outside the frame.
3635 if (!targetFrame) {
3636 return NS_ERROR_INVALID_ARG;
3637 }
3639 // Convert point to coordinates relative to the target frame, which is
3640 // what targetFrame's SelectByTypeAtPoint expects.
3641 nsPoint relPoint =
3642 nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, pt, targetFrame);
3644 nsresult rv =
3645 static_cast<nsFrame*>(targetFrame)->
3646 SelectByTypeAtPoint(GetPresContext(), relPoint, amount, amount,
3647 nsFrame::SELECT_ACCUMULATE);
3648 *_retval = !NS_FAILED(rv);
3649 return NS_OK;
3650 }
3652 static nsIDocument::additionalSheetType
3653 convertSheetType(uint32_t aSheetType)
3654 {
3655 switch(aSheetType) {
3656 case nsDOMWindowUtils::AGENT_SHEET:
3657 return nsIDocument::eAgentSheet;
3658 case nsDOMWindowUtils::USER_SHEET:
3659 return nsIDocument::eUserSheet;
3660 case nsDOMWindowUtils::AUTHOR_SHEET:
3661 return nsIDocument::eAuthorSheet;
3662 default:
3663 NS_ASSERTION(false, "wrong type");
3664 // we must return something although this should never happen
3665 return nsIDocument::SheetTypeCount;
3666 }
3667 }
3669 NS_IMETHODIMP
3670 nsDOMWindowUtils::LoadSheet(nsIURI *aSheetURI, uint32_t aSheetType)
3671 {
3672 if (!nsContentUtils::IsCallerChrome()) {
3673 return NS_ERROR_DOM_SECURITY_ERR;
3674 }
3676 NS_ENSURE_ARG_POINTER(aSheetURI);
3677 NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
3678 aSheetType == USER_SHEET ||
3679 aSheetType == AUTHOR_SHEET);
3681 nsCOMPtr<nsIDocument> doc = GetDocument();
3682 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
3684 nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
3686 return doc->LoadAdditionalStyleSheet(type, aSheetURI);
3687 }
3689 NS_IMETHODIMP
3690 nsDOMWindowUtils::RemoveSheet(nsIURI *aSheetURI, uint32_t aSheetType)
3691 {
3692 if (!nsContentUtils::IsCallerChrome()) {
3693 return NS_ERROR_DOM_SECURITY_ERR;
3694 }
3696 NS_ENSURE_ARG_POINTER(aSheetURI);
3697 NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
3698 aSheetType == USER_SHEET ||
3699 aSheetType == AUTHOR_SHEET);
3701 nsCOMPtr<nsIDocument> doc = GetDocument();
3702 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
3704 nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
3706 doc->RemoveAdditionalStyleSheet(type, aSheetURI);
3707 return NS_OK;
3708 }
3710 NS_IMETHODIMP
3711 nsDOMWindowUtils::GetIsHandlingUserInput(bool* aHandlingUserInput)
3712 {
3713 if (!nsContentUtils::IsCallerChrome()) {
3714 return NS_ERROR_DOM_SECURITY_ERR;
3715 }
3717 *aHandlingUserInput = EventStateManager::IsHandlingUserInput();
3719 return NS_OK;
3720 }
3722 NS_IMETHODIMP
3723 nsDOMWindowUtils::AllowScriptsToClose()
3724 {
3725 if (!nsContentUtils::IsCallerChrome()) {
3726 return NS_ERROR_DOM_SECURITY_ERR;
3727 }
3728 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3729 NS_ENSURE_STATE(window);
3730 static_cast<nsGlobalWindow*>(window.get())->AllowScriptsToClose();
3731 return NS_OK;
3732 }
3734 NS_IMETHODIMP
3735 nsDOMWindowUtils::GetIsParentWindowMainWidgetVisible(bool* aIsVisible)
3736 {
3737 if (!nsContentUtils::IsCallerChrome()) {
3738 return NS_ERROR_DOM_SECURITY_ERR;
3739 }
3741 // this should reflect the "is parent window visible" logic in
3742 // nsWindowWatcher::OpenWindowInternal()
3743 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3744 NS_ENSURE_STATE(window);
3746 nsCOMPtr<nsIWidget> parentWidget;
3747 nsIDocShell *docShell = window->GetDocShell();
3748 if (docShell) {
3749 if (TabChild *tabChild = TabChild::GetFrom(docShell)) {
3750 if (!tabChild->SendIsParentWindowMainWidgetVisible(aIsVisible))
3751 return NS_ERROR_FAILURE;
3752 return NS_OK;
3753 }
3755 nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
3756 docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
3757 nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(parentTreeOwner));
3758 if (parentWindow) {
3759 parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
3760 }
3761 }
3762 if (!parentWidget) {
3763 return NS_ERROR_NOT_AVAILABLE;
3764 }
3766 *aIsVisible = parentWidget->IsVisible();
3767 return NS_OK;
3768 }
3770 NS_IMETHODIMP
3771 nsDOMWindowUtils::IsNodeDisabledForEvents(nsIDOMNode* aNode, bool* aRetVal)
3772 {
3773 *aRetVal = false;
3774 if (!nsContentUtils::IsCallerChrome()) {
3775 return NS_ERROR_DOM_SECURITY_ERR;
3776 }
3777 nsCOMPtr<nsINode> n = do_QueryInterface(aNode);
3778 nsINode* node = n;
3779 while (node) {
3780 if (node->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
3781 nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
3782 if (fc && fc->IsDisabledForEvents(NS_EVENT_NULL)) {
3783 *aRetVal = true;
3784 break;
3785 }
3786 }
3787 node = node->GetParentNode();
3788 }
3790 return NS_OK;
3791 }
3793 NS_IMETHODIMP
3794 nsDOMWindowUtils::SetPaintFlashing(bool aPaintFlashing)
3795 {
3796 nsPresContext* presContext = GetPresContext();
3797 if (presContext) {
3798 presContext->SetPaintFlashing(aPaintFlashing);
3799 // Clear paint flashing colors
3800 nsIPresShell* presShell = GetPresShell();
3801 if (!aPaintFlashing && presShell) {
3802 nsIFrame* rootFrame = presShell->GetRootFrame();
3803 if (rootFrame) {
3804 rootFrame->InvalidateFrameSubtree();
3805 }
3806 }
3807 }
3808 return NS_OK;
3809 }
3811 NS_IMETHODIMP
3812 nsDOMWindowUtils::GetPaintFlashing(bool* aRetVal)
3813 {
3814 *aRetVal = false;
3815 nsPresContext* presContext = GetPresContext();
3816 if (presContext) {
3817 *aRetVal = presContext->GetPaintFlashing();
3818 }
3819 return NS_OK;
3820 }
3822 NS_IMETHODIMP
3823 nsDOMWindowUtils::DispatchEventToChromeOnly(nsIDOMEventTarget* aTarget,
3824 nsIDOMEvent* aEvent,
3825 bool* aRetVal)
3826 {
3827 *aRetVal = false;
3828 if (!nsContentUtils::IsCallerChrome()) {
3829 return NS_ERROR_DOM_SECURITY_ERR;
3830 }
3831 NS_ENSURE_STATE(aTarget && aEvent);
3832 aEvent->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
3833 aTarget->DispatchEvent(aEvent, aRetVal);
3834 return NS_OK;
3835 }
3837 NS_IMETHODIMP
3838 nsDOMWindowUtils::RunInStableState(nsIRunnable *runnable)
3839 {
3840 if (!nsContentUtils::IsCallerChrome()) {
3841 return NS_ERROR_DOM_SECURITY_ERR;
3842 }
3844 nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
3845 if (!appShell) {
3846 return NS_ERROR_NOT_AVAILABLE;
3847 }
3849 return appShell->RunInStableState(runnable);
3850 }
3852 NS_IMETHODIMP
3853 nsDOMWindowUtils::RunBeforeNextEvent(nsIRunnable *runnable)
3854 {
3855 if (!nsContentUtils::IsCallerChrome()) {
3856 return NS_ERROR_DOM_SECURITY_ERR;
3857 }
3859 nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
3860 if (!appShell) {
3861 return NS_ERROR_NOT_AVAILABLE;
3862 }
3864 return appShell->RunBeforeNextEvent(runnable);
3865 }
3867 NS_IMETHODIMP
3868 nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
3869 const nsAString& aProperty,
3870 nsAString& aResult)
3871 {
3872 if (!nsContentUtils::IsCallerChrome()) {
3873 return NS_ERROR_DOM_SECURITY_ERR;
3874 }
3876 nsCOMPtr<Element> element = do_QueryInterface(aElement);
3877 if (!element) {
3878 return NS_ERROR_INVALID_ARG;
3879 }
3881 nsRefPtr<nsROCSSPrimitiveValue> cssValue = nullptr;
3882 nsIFrame* frame = element->GetPrimaryFrame();
3883 if (frame && nsLayoutUtils::AreAsyncAnimationsEnabled()) {
3884 if (aProperty.EqualsLiteral("opacity")) {
3885 Layer* layer =
3886 FrameLayerBuilder::GetDedicatedLayer(frame,
3887 nsDisplayItem::TYPE_OPACITY);
3888 if (layer) {
3889 float value;
3890 ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
3891 if (forwarder && forwarder->HasShadowManager()) {
3892 forwarder->GetShadowManager()->SendGetOpacity(
3893 layer->AsShadowableLayer()->GetShadow(), &value);
3894 cssValue = new nsROCSSPrimitiveValue;
3895 cssValue->SetNumber(value);
3896 }
3897 }
3898 } else if (aProperty.EqualsLiteral("transform")) {
3899 Layer* layer =
3900 FrameLayerBuilder::GetDedicatedLayer(frame,
3901 nsDisplayItem::TYPE_TRANSFORM);
3902 if (layer) {
3903 ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
3904 if (forwarder && forwarder->HasShadowManager()) {
3905 MaybeTransform transform;
3906 forwarder->GetShadowManager()->SendGetAnimationTransform(
3907 layer->AsShadowableLayer()->GetShadow(), &transform);
3908 if (transform.type() == MaybeTransform::Tgfx3DMatrix) {
3909 cssValue =
3910 nsComputedDOMStyle::MatrixToCSSValue(transform.get_gfx3DMatrix());
3911 }
3912 }
3913 }
3914 }
3915 }
3917 if (cssValue) {
3918 nsString text;
3919 ErrorResult rv;
3920 cssValue->GetCssText(text, rv);
3921 aResult.Assign(text);
3922 return rv.ErrorCode();
3923 } else {
3924 aResult.Truncate();
3925 }
3927 return NS_OK;
3928 }
3930 NS_IMETHODIMP
3931 nsDOMWindowUtils::GetOMTAOrComputedStyle(nsIDOMElement* aElement,
3932 const nsAString& aProperty,
3933 nsAString& aResult)
3934 {
3935 if (!nsContentUtils::IsCallerChrome()) {
3936 return NS_ERROR_DOM_SECURITY_ERR;
3937 }
3939 // Try to get OMTA style
3940 nsresult rv = GetOMTAStyle(aElement, aProperty, aResult);
3941 if (NS_FAILED(rv) || !aResult.IsEmpty()) {
3942 return rv;
3943 }
3945 // Otherwise, fall back to computed style
3946 nsCOMPtr<Element> element = do_QueryInterface(aElement);
3947 if (!element) {
3948 return NS_ERROR_INVALID_ARG;
3949 }
3950 nsCOMPtr<nsIDOMCSSStyleDeclaration> style;
3951 rv = element->GetCurrentDoc()->GetWindow()->
3952 GetComputedStyle(aElement, aProperty, getter_AddRefs(style));
3953 NS_ENSURE_SUCCESS(rv, rv);
3955 return style->GetPropertyValue(aProperty, aResult);
3956 }
3958 NS_IMETHODIMP
3959 nsDOMWindowUtils::GetAudioMuted(bool* aMuted)
3960 {
3961 if (!nsContentUtils::IsCallerChrome()) {
3962 return NS_ERROR_DOM_SECURITY_ERR;
3963 }
3964 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3965 NS_ENSURE_STATE(window);
3967 *aMuted = window->GetAudioMuted();
3968 return NS_OK;
3969 }
3971 NS_IMETHODIMP
3972 nsDOMWindowUtils::SetAudioMuted(bool aMuted)
3973 {
3974 if (!nsContentUtils::IsCallerChrome()) {
3975 return NS_ERROR_DOM_SECURITY_ERR;
3976 }
3977 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3978 NS_ENSURE_STATE(window);
3980 window->SetAudioMuted(aMuted);
3981 return NS_OK;
3982 }
3984 NS_IMETHODIMP
3985 nsDOMWindowUtils::GetAudioVolume(float* aVolume)
3986 {
3987 if (!nsContentUtils::IsCallerChrome()) {
3988 return NS_ERROR_DOM_SECURITY_ERR;
3989 }
3990 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
3991 NS_ENSURE_STATE(window);
3993 *aVolume = window->GetAudioVolume();
3994 return NS_OK;
3995 }
3997 NS_IMETHODIMP
3998 nsDOMWindowUtils::SetAudioVolume(float aVolume)
3999 {
4000 if (!nsContentUtils::IsCallerChrome()) {
4001 return NS_ERROR_DOM_SECURITY_ERR;
4002 }
4003 nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
4004 NS_ENSURE_STATE(window);
4006 return window->SetAudioVolume(aVolume);
4007 }
4009 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
4010 NS_INTERFACE_MAP_ENTRY(nsISupports)
4011 NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
4012 NS_INTERFACE_MAP_END
4014 NS_IMPL_ADDREF(nsTranslationNodeList)
4015 NS_IMPL_RELEASE(nsTranslationNodeList)
4017 NS_IMETHODIMP
4018 nsTranslationNodeList::Item(uint32_t aIndex, nsIDOMNode** aRetVal)
4019 {
4020 NS_ENSURE_ARG_POINTER(aRetVal);
4021 NS_IF_ADDREF(*aRetVal = mNodes.SafeElementAt(aIndex));
4022 return NS_OK;
4023 }
4025 NS_IMETHODIMP
4026 nsTranslationNodeList::IsTranslationRootAtIndex(uint32_t aIndex, bool* aRetVal)
4027 {
4028 NS_ENSURE_ARG_POINTER(aRetVal);
4029 if (aIndex >= mLength) {
4030 *aRetVal = false;
4031 return NS_OK;
4032 }
4034 *aRetVal = mNodeIsRoot.ElementAt(aIndex);
4035 return NS_OK;
4036 }
4038 NS_IMETHODIMP
4039 nsTranslationNodeList::GetLength(uint32_t* aRetVal)
4040 {
4041 NS_ENSURE_ARG_POINTER(aRetVal);
4042 *aRetVal = mLength;
4043 return NS_OK;
4044 }