1 : /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
2 : /* vim: set sw=2 ts=8 et tw=80 : */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Content App.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * The Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2009
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "TabParent.h"
40 :
41 : #include "mozilla/dom/ContentParent.h"
42 : #include "mozilla/ipc/DocumentRendererParent.h"
43 : #include "mozilla/layout/RenderFrameParent.h"
44 : #include "mozilla/docshell/OfflineCacheUpdateParent.h"
45 :
46 : #include "nsIURI.h"
47 : #include "nsFocusManager.h"
48 : #include "nsCOMPtr.h"
49 : #include "nsServiceManagerUtils.h"
50 : #include "nsIDOMElement.h"
51 : #include "nsEventDispatcher.h"
52 : #include "nsIDOMEventTarget.h"
53 : #include "nsIWindowWatcher.h"
54 : #include "nsIDOMWindow.h"
55 : #include "nsPIDOMWindow.h"
56 : #include "TabChild.h"
57 : #include "nsIDOMEvent.h"
58 : #include "nsIPrivateDOMEvent.h"
59 : #include "nsFrameLoader.h"
60 : #include "nsNetUtil.h"
61 : #include "nsContentUtils.h"
62 : #include "nsContentPermissionHelper.h"
63 : #include "nsIDOMHTMLFrameElement.h"
64 : #include "nsIDialogCreator.h"
65 : #include "nsThreadUtils.h"
66 : #include "nsSerializationHelper.h"
67 : #include "nsIPromptFactory.h"
68 : #include "nsIContent.h"
69 : #include "nsIWidget.h"
70 : #include "nsIViewManager.h"
71 : #include "mozilla/unused.h"
72 : #include "nsDebug.h"
73 :
74 : using namespace mozilla::dom;
75 : using namespace mozilla::ipc;
76 : using namespace mozilla::layout;
77 : using namespace mozilla::widget;
78 :
79 : // The flags passed by the webProgress notifications are 16 bits shifted
80 : // from the ones registered by webProgressListeners.
81 : #define NOTIFY_FLAG_SHIFT 16
82 :
83 : namespace mozilla {
84 : namespace dom {
85 :
86 : TabParent *TabParent::mIMETabParent = nsnull;
87 :
88 0 : NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
89 :
90 0 : TabParent::TabParent()
91 : : mIMEComposing(false)
92 : , mIMECompositionEnding(false)
93 : , mIMESeqno(0)
94 : , mDPI(0)
95 0 : , mActive(false)
96 : {
97 0 : }
98 :
99 0 : TabParent::~TabParent()
100 : {
101 0 : }
102 :
103 : void
104 0 : TabParent::SetOwnerElement(nsIDOMElement* aElement)
105 : {
106 0 : mFrameElement = aElement;
107 :
108 : // Cache the DPI of the screen, since we may lose the element/widget later
109 0 : if (aElement) {
110 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
111 0 : NS_ABORT_IF_FALSE(widget, "Non-null OwnerElement must provide a widget!");
112 0 : mDPI = widget->GetDPI();
113 : }
114 0 : }
115 :
116 : void
117 0 : TabParent::Destroy()
118 : {
119 : // If this fails, it's most likely due to a content-process crash,
120 : // and auto-cleanup will kick in. Otherwise, the child side will
121 : // destroy itself and send back __delete__().
122 0 : unused << SendDestroy();
123 :
124 0 : for (size_t i = 0; i < ManagedPRenderFrameParent().Length(); ++i) {
125 : RenderFrameParent* rfp =
126 0 : static_cast<RenderFrameParent*>(ManagedPRenderFrameParent()[i]);
127 0 : rfp->Destroy();
128 : }
129 0 : }
130 :
131 : void
132 0 : TabParent::ActorDestroy(ActorDestroyReason why)
133 : {
134 0 : if (mIMETabParent == this)
135 0 : mIMETabParent = nsnull;
136 0 : nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
137 0 : if (frameLoader) {
138 0 : frameLoader->DestroyChild();
139 : }
140 0 : }
141 :
142 : bool
143 0 : TabParent::RecvMoveFocus(const bool& aForward)
144 : {
145 0 : nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
146 0 : if (fm) {
147 0 : nsCOMPtr<nsIDOMElement> dummy;
148 : PRUint32 type = aForward ? PRUint32(nsIFocusManager::MOVEFOCUS_FORWARD)
149 0 : : PRUint32(nsIFocusManager::MOVEFOCUS_BACKWARD);
150 0 : fm->MoveFocus(nsnull, mFrameElement, type, nsIFocusManager::FLAG_BYKEY,
151 0 : getter_AddRefs(dummy));
152 : }
153 0 : return true;
154 : }
155 :
156 : bool
157 0 : TabParent::RecvEvent(const RemoteDOMEvent& aEvent)
158 : {
159 0 : nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(aEvent.mEvent);
160 0 : NS_ENSURE_TRUE(event, true);
161 :
162 0 : nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mFrameElement);
163 0 : NS_ENSURE_TRUE(target, true);
164 :
165 : bool dummy;
166 0 : target->DispatchEvent(event, &dummy);
167 0 : return true;
168 : }
169 :
170 : bool
171 0 : TabParent::AnswerCreateWindow(PBrowserParent** retval)
172 : {
173 0 : if (!mBrowserDOMWindow) {
174 0 : return false;
175 : }
176 :
177 : // Get a new rendering area from the browserDOMWin. We don't want
178 : // to be starting any loads here, so get it with a null URI.
179 0 : nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
180 0 : mBrowserDOMWindow->OpenURIInFrame(nsnull, nsnull,
181 : nsIBrowserDOMWindow::OPEN_NEWTAB,
182 : nsIBrowserDOMWindow::OPEN_NEW,
183 0 : getter_AddRefs(frameLoaderOwner));
184 0 : if (!frameLoaderOwner) {
185 0 : return false;
186 : }
187 :
188 0 : nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
189 0 : if (!frameLoader) {
190 0 : return false;
191 : }
192 :
193 0 : *retval = frameLoader->GetRemoteBrowser();
194 0 : return true;
195 : }
196 :
197 : void
198 0 : TabParent::LoadURL(nsIURI* aURI)
199 : {
200 0 : nsCString spec;
201 0 : aURI->GetSpec(spec);
202 :
203 0 : unused << SendLoadURL(spec);
204 0 : }
205 :
206 : void
207 0 : TabParent::Show(const nsIntSize& size)
208 : {
209 : // sigh
210 0 : unused << SendShow(size);
211 0 : }
212 :
213 : void
214 0 : TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
215 : {
216 0 : unused << SendUpdateDimensions(rect, size);
217 0 : }
218 :
219 : void
220 0 : TabParent::Activate()
221 : {
222 0 : mActive = true;
223 0 : unused << SendActivate();
224 0 : }
225 :
226 : void
227 0 : TabParent::Deactivate()
228 : {
229 0 : mActive = false;
230 0 : unused << SendDeactivate();
231 0 : }
232 :
233 : bool
234 0 : TabParent::Active()
235 : {
236 0 : return mActive;
237 : }
238 :
239 : NS_IMETHODIMP
240 0 : TabParent::Init(nsIDOMWindow *window)
241 : {
242 0 : return NS_OK;
243 : }
244 :
245 : NS_IMETHODIMP
246 0 : TabParent::GetState(PRUint32 *aState)
247 : {
248 0 : NS_ENSURE_ARG(aState);
249 0 : NS_WARNING("SecurityState not valid here");
250 0 : *aState = 0;
251 0 : return NS_OK;
252 : }
253 :
254 : NS_IMETHODIMP
255 0 : TabParent::GetTooltipText(nsAString & aTooltipText)
256 : {
257 0 : aTooltipText.Truncate();
258 0 : return NS_OK;
259 : }
260 :
261 : PDocumentRendererParent*
262 0 : TabParent::AllocPDocumentRenderer(const nsRect& documentRect,
263 : const gfxMatrix& transform,
264 : const nsString& bgcolor,
265 : const PRUint32& renderFlags,
266 : const bool& flushLayout,
267 : const nsIntSize& renderSize)
268 : {
269 0 : return new DocumentRendererParent();
270 : }
271 :
272 : bool
273 0 : TabParent::DeallocPDocumentRenderer(PDocumentRendererParent* actor)
274 : {
275 0 : delete actor;
276 0 : return true;
277 : }
278 :
279 : PContentPermissionRequestParent*
280 0 : TabParent::AllocPContentPermissionRequest(const nsCString& type, const IPC::URI& uri)
281 : {
282 0 : return new ContentPermissionRequestParent(type, mFrameElement, uri);
283 : }
284 :
285 : bool
286 0 : TabParent::DeallocPContentPermissionRequest(PContentPermissionRequestParent* actor)
287 : {
288 0 : delete actor;
289 0 : return true;
290 : }
291 :
292 : void
293 0 : TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
294 : PRInt32 aButton, PRInt32 aClickCount,
295 : PRInt32 aModifiers, bool aIgnoreRootScrollFrame)
296 : {
297 0 : unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY,
298 : aButton, aClickCount,
299 0 : aModifiers, aIgnoreRootScrollFrame);
300 0 : }
301 :
302 : void
303 0 : TabParent::SendKeyEvent(const nsAString& aType,
304 : PRInt32 aKeyCode,
305 : PRInt32 aCharCode,
306 : PRInt32 aModifiers,
307 : bool aPreventDefault)
308 : {
309 0 : unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
310 0 : aModifiers, aPreventDefault);
311 0 : }
312 :
313 0 : bool TabParent::SendRealMouseEvent(nsMouseEvent& event)
314 : {
315 0 : return PBrowserParent::SendRealMouseEvent(event);
316 : }
317 :
318 0 : bool TabParent::SendMouseScrollEvent(nsMouseScrollEvent& event)
319 : {
320 0 : return PBrowserParent::SendMouseScrollEvent(event);
321 : }
322 :
323 0 : bool TabParent::SendRealKeyEvent(nsKeyEvent& event)
324 : {
325 0 : return PBrowserParent::SendRealKeyEvent(event);
326 : }
327 :
328 : bool
329 0 : TabParent::RecvSyncMessage(const nsString& aMessage,
330 : const nsString& aJSON,
331 : InfallibleTArray<nsString>* aJSONRetVal)
332 : {
333 0 : return ReceiveMessage(aMessage, true, aJSON, aJSONRetVal);
334 : }
335 :
336 : bool
337 0 : TabParent::RecvAsyncMessage(const nsString& aMessage,
338 : const nsString& aJSON)
339 : {
340 0 : return ReceiveMessage(aMessage, false, aJSON, nsnull);
341 : }
342 :
343 : bool
344 0 : TabParent::RecvSetCursor(const PRUint32& aCursor)
345 : {
346 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
347 0 : if (widget) {
348 0 : widget->SetCursor((nsCursor) aCursor);
349 : }
350 0 : return true;
351 : }
352 :
353 : bool
354 0 : TabParent::RecvSetBackgroundColor(const nscolor& aColor)
355 : {
356 0 : if (nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader()) {
357 0 : if (RenderFrameParent* frame = frameLoader->GetCurrentRemoteFrame()) {
358 0 : frame->SetBackgroundColor(aColor);
359 : }
360 : }
361 0 : return true;
362 : }
363 :
364 : bool
365 0 : TabParent::RecvNotifyIMEFocus(const bool& aFocus,
366 : nsIMEUpdatePreference* aPreference,
367 : PRUint32* aSeqno)
368 : {
369 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
370 0 : if (!widget)
371 0 : return true;
372 :
373 0 : *aSeqno = mIMESeqno;
374 0 : mIMETabParent = aFocus ? this : nsnull;
375 0 : mIMESelectionAnchor = 0;
376 0 : mIMESelectionFocus = 0;
377 0 : nsresult rv = widget->OnIMEFocusChange(aFocus);
378 :
379 0 : if (aFocus) {
380 0 : if (NS_SUCCEEDED(rv) && rv != NS_SUCCESS_IME_NO_UPDATES) {
381 0 : *aPreference = widget->GetIMEUpdatePreference();
382 : } else {
383 0 : aPreference->mWantUpdates = false;
384 0 : aPreference->mWantHints = false;
385 : }
386 : } else {
387 0 : mIMECacheText.Truncate(0);
388 : }
389 0 : return true;
390 : }
391 :
392 : bool
393 0 : TabParent::RecvNotifyIMETextChange(const PRUint32& aStart,
394 : const PRUint32& aEnd,
395 : const PRUint32& aNewEnd)
396 : {
397 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
398 0 : if (!widget)
399 0 : return true;
400 :
401 0 : widget->OnIMETextChange(aStart, aEnd, aNewEnd);
402 0 : return true;
403 : }
404 :
405 : bool
406 0 : TabParent::RecvNotifyIMESelection(const PRUint32& aSeqno,
407 : const PRUint32& aAnchor,
408 : const PRUint32& aFocus)
409 : {
410 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
411 0 : if (!widget)
412 0 : return true;
413 :
414 0 : if (aSeqno == mIMESeqno) {
415 0 : mIMESelectionAnchor = aAnchor;
416 0 : mIMESelectionFocus = aFocus;
417 0 : widget->OnIMESelectionChange();
418 : }
419 0 : return true;
420 : }
421 :
422 : bool
423 0 : TabParent::RecvNotifyIMETextHint(const nsString& aText)
424 : {
425 : // Replace our cache with new text
426 0 : mIMECacheText = aText;
427 0 : return true;
428 : }
429 :
430 : /**
431 : * Try to answer query event using cached text.
432 : *
433 : * For NS_QUERY_SELECTED_TEXT, fail if the cache doesn't contain the whole
434 : * selected range. (This shouldn't happen because PuppetWidget should have
435 : * already sent the whole selection.)
436 : *
437 : * For NS_QUERY_TEXT_CONTENT, fail only if the cache doesn't overlap with
438 : * the queried range. Note the difference from above. We use
439 : * this behavior because a normal NS_QUERY_TEXT_CONTENT event is allowed to
440 : * have out-of-bounds offsets, so that widget can request content without
441 : * knowing the exact length of text. It's up to widget to handle cases when
442 : * the returned offset/length are different from the queried offset/length.
443 : */
444 : bool
445 0 : TabParent::HandleQueryContentEvent(nsQueryContentEvent& aEvent)
446 : {
447 0 : aEvent.mSucceeded = false;
448 0 : aEvent.mWasAsync = false;
449 0 : aEvent.mReply.mFocusedWidget = nsCOMPtr<nsIWidget>(GetWidget()).get();
450 :
451 0 : switch (aEvent.message)
452 : {
453 : case NS_QUERY_SELECTED_TEXT:
454 : {
455 0 : aEvent.mReply.mOffset = NS_MIN(mIMESelectionAnchor, mIMESelectionFocus);
456 0 : if (mIMESelectionAnchor == mIMESelectionFocus) {
457 0 : aEvent.mReply.mString.Truncate(0);
458 : } else {
459 0 : if (mIMESelectionAnchor > mIMECacheText.Length() ||
460 0 : mIMESelectionFocus > mIMECacheText.Length()) {
461 0 : break;
462 : }
463 : PRUint32 selLen = mIMESelectionAnchor > mIMESelectionFocus ?
464 : mIMESelectionAnchor - mIMESelectionFocus :
465 0 : mIMESelectionFocus - mIMESelectionAnchor;
466 : aEvent.mReply.mString = Substring(mIMECacheText,
467 : aEvent.mReply.mOffset,
468 0 : selLen);
469 : }
470 0 : aEvent.mReply.mReversed = mIMESelectionFocus < mIMESelectionAnchor;
471 0 : aEvent.mReply.mHasSelection = true;
472 0 : aEvent.mSucceeded = true;
473 : }
474 0 : break;
475 : case NS_QUERY_TEXT_CONTENT:
476 : {
477 0 : PRUint32 inputOffset = aEvent.mInput.mOffset,
478 0 : inputEnd = inputOffset + aEvent.mInput.mLength;
479 :
480 0 : if (inputEnd > mIMECacheText.Length()) {
481 0 : inputEnd = mIMECacheText.Length();
482 : }
483 0 : if (inputEnd < inputOffset) {
484 0 : break;
485 : }
486 0 : aEvent.mReply.mOffset = inputOffset;
487 : aEvent.mReply.mString = Substring(mIMECacheText,
488 : inputOffset,
489 0 : inputEnd - inputOffset);
490 0 : aEvent.mSucceeded = true;
491 : }
492 0 : break;
493 : }
494 0 : return true;
495 : }
496 :
497 : bool
498 0 : TabParent::SendCompositionEvent(nsCompositionEvent& event)
499 : {
500 0 : mIMEComposing = event.message != NS_COMPOSITION_END;
501 0 : mIMECompositionStart = NS_MIN(mIMESelectionAnchor, mIMESelectionFocus);
502 0 : if (mIMECompositionEnding)
503 0 : return true;
504 0 : event.seqno = ++mIMESeqno;
505 0 : return PBrowserParent::SendCompositionEvent(event);
506 : }
507 :
508 : /**
509 : * During ResetInputState or CancelComposition, widget usually sends a
510 : * NS_TEXT_TEXT event to finalize or clear the composition, respectively
511 : *
512 : * Because the event will not reach content in time, we intercept it
513 : * here and pass the text as the EndIMEComposition return value
514 : */
515 : bool
516 0 : TabParent::SendTextEvent(nsTextEvent& event)
517 : {
518 0 : if (mIMECompositionEnding) {
519 0 : mIMECompositionText = event.theText;
520 0 : return true;
521 : }
522 :
523 : // We must be able to simulate the selection because
524 : // we might not receive selection updates in time
525 0 : if (!mIMEComposing) {
526 0 : mIMECompositionStart = NS_MIN(mIMESelectionAnchor, mIMESelectionFocus);
527 : }
528 : mIMESelectionAnchor = mIMESelectionFocus =
529 0 : mIMECompositionStart + event.theText.Length();
530 :
531 0 : event.seqno = ++mIMESeqno;
532 0 : return PBrowserParent::SendTextEvent(event);
533 : }
534 :
535 : bool
536 0 : TabParent::SendSelectionEvent(nsSelectionEvent& event)
537 : {
538 0 : mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
539 0 : mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
540 0 : event.seqno = ++mIMESeqno;
541 0 : return PBrowserParent::SendSelectionEvent(event);
542 : }
543 :
544 : bool
545 0 : TabParent::RecvEndIMEComposition(const bool& aCancel,
546 : nsString* aComposition)
547 : {
548 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
549 0 : if (!widget)
550 0 : return true;
551 :
552 0 : mIMECompositionEnding = true;
553 :
554 0 : if (aCancel) {
555 0 : widget->CancelIMEComposition();
556 : } else {
557 0 : widget->ResetInputState();
558 : }
559 :
560 0 : mIMECompositionEnding = false;
561 0 : *aComposition = mIMECompositionText;
562 0 : mIMECompositionText.Truncate(0);
563 0 : return true;
564 : }
565 :
566 : bool
567 0 : TabParent::RecvGetInputContext(PRInt32* aIMEEnabled,
568 : PRInt32* aIMEOpen)
569 : {
570 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
571 0 : if (!widget) {
572 0 : *aIMEEnabled = IMEState::DISABLED;
573 0 : *aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
574 0 : return true;
575 : }
576 :
577 0 : InputContext context = widget->GetInputContext();
578 0 : *aIMEEnabled = static_cast<PRInt32>(context.mIMEState.mEnabled);
579 0 : *aIMEOpen = static_cast<PRInt32>(context.mIMEState.mOpen);
580 0 : return true;
581 : }
582 :
583 : bool
584 0 : TabParent::RecvSetInputContext(const PRInt32& aIMEEnabled,
585 : const PRInt32& aIMEOpen,
586 : const nsString& aType,
587 : const nsString& aActionHint,
588 : const PRInt32& aCause,
589 : const PRInt32& aFocusChange)
590 : {
591 : // mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus
592 : // When the input mode is set to anything but IMEState::DISABLED,
593 : // mIMETabParent should be set to this
594 : mIMETabParent =
595 0 : aIMEEnabled != static_cast<PRInt32>(IMEState::DISABLED) ? this : nsnull;
596 0 : nsCOMPtr<nsIWidget> widget = GetWidget();
597 0 : if (!widget || !AllowContentIME())
598 0 : return true;
599 :
600 0 : InputContext context;
601 0 : context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled);
602 0 : context.mIMEState.mOpen = static_cast<IMEState::Open>(aIMEOpen);
603 0 : context.mHTMLInputType.Assign(aType);
604 0 : context.mActionHint.Assign(aActionHint);
605 : InputContextAction action(
606 : static_cast<InputContextAction::Cause>(aCause),
607 0 : static_cast<InputContextAction::FocusChange>(aFocusChange));
608 0 : widget->SetInputContext(context, action);
609 :
610 0 : nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
611 0 : if (!observerService)
612 0 : return true;
613 :
614 0 : nsAutoString state;
615 0 : state.AppendInt(aIMEEnabled);
616 0 : observerService->NotifyObservers(nsnull, "ime-enabled-state-changed", state.get());
617 :
618 0 : return true;
619 : }
620 :
621 : bool
622 0 : TabParent::RecvGetDPI(float* aValue)
623 : {
624 0 : NS_ABORT_IF_FALSE(mDPI > 0,
625 : "Must not ask for DPI before OwnerElement is received!");
626 0 : *aValue = mDPI;
627 0 : return true;
628 : }
629 :
630 : bool
631 0 : TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
632 : {
633 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
634 0 : if (content) {
635 0 : nsIPresShell* shell = content->OwnerDoc()->GetShell();
636 0 : if (shell) {
637 0 : nsIViewManager* vm = shell->GetViewManager();
638 0 : nsCOMPtr<nsIWidget> widget;
639 0 : vm->GetRootWidget(getter_AddRefs(widget));
640 0 : if (widget) {
641 : *aValue = reinterpret_cast<WindowsHandle>(
642 0 : widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
643 0 : return true;
644 : }
645 : }
646 : }
647 0 : return false;
648 : }
649 :
650 : bool
651 0 : TabParent::ReceiveMessage(const nsString& aMessage,
652 : bool aSync,
653 : const nsString& aJSON,
654 : InfallibleTArray<nsString>* aJSONRetVal)
655 : {
656 0 : nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
657 0 : if (frameLoader && frameLoader->GetFrameMessageManager()) {
658 : nsRefPtr<nsFrameMessageManager> manager =
659 0 : frameLoader->GetFrameMessageManager();
660 0 : JSContext* ctx = manager->GetJSContext();
661 0 : JSAutoRequest ar(ctx);
662 0 : PRUint32 len = 0; //TODO: obtain a real value in bug 572685
663 : // Because we want JS messages to have always the same properties,
664 : // create array even if len == 0.
665 0 : JSObject* objectsArray = JS_NewArrayObject(ctx, len, NULL);
666 0 : if (!objectsArray) {
667 0 : return false;
668 : }
669 :
670 : manager->ReceiveMessage(mFrameElement,
671 : aMessage,
672 : aSync,
673 : aJSON,
674 : objectsArray,
675 0 : aJSONRetVal);
676 : }
677 0 : return true;
678 : }
679 :
680 : // nsIAuthPromptProvider
681 :
682 : // This method is largely copied from nsDocShell::GetAuthPrompt
683 : NS_IMETHODIMP
684 0 : TabParent::GetAuthPrompt(PRUint32 aPromptReason, const nsIID& iid,
685 : void** aResult)
686 : {
687 : // we're either allowing auth, or it's a proxy request
688 : nsresult rv;
689 : nsCOMPtr<nsIPromptFactory> wwatch =
690 0 : do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
691 0 : NS_ENSURE_SUCCESS(rv, rv);
692 :
693 0 : nsCOMPtr<nsIDOMWindow> window;
694 0 : nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
695 0 : if (frame)
696 0 : window = do_QueryInterface(frame->OwnerDoc()->GetWindow());
697 :
698 : // Get an auth prompter for our window so that the parenting
699 : // of the dialogs works as it should when using tabs.
700 0 : return wwatch->GetPrompt(window, iid,
701 0 : reinterpret_cast<void**>(aResult));
702 : }
703 :
704 : PContentDialogParent*
705 0 : TabParent::AllocPContentDialog(const PRUint32& aType,
706 : const nsCString& aName,
707 : const nsCString& aFeatures,
708 : const InfallibleTArray<int>& aIntParams,
709 : const InfallibleTArray<nsString>& aStringParams)
710 : {
711 0 : ContentDialogParent* parent = new ContentDialogParent();
712 : nsCOMPtr<nsIDialogParamBlock> params =
713 0 : do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID);
714 0 : TabChild::ArraysToParams(aIntParams, aStringParams, params);
715 : mDelayedDialogs.AppendElement(new DelayedDialogData(parent, aType, aName,
716 0 : aFeatures, params));
717 : nsRefPtr<nsIRunnable> ev =
718 0 : NS_NewRunnableMethod(this, &TabParent::HandleDelayedDialogs);
719 0 : NS_DispatchToCurrentThread(ev);
720 0 : return parent;
721 : }
722 :
723 : void
724 0 : TabParent::HandleDelayedDialogs()
725 : {
726 0 : nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
727 0 : nsCOMPtr<nsIDOMWindow> window;
728 0 : nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
729 0 : if (frame) {
730 0 : window = do_QueryInterface(frame->OwnerDoc()->GetWindow());
731 : }
732 0 : nsCOMPtr<nsIDialogCreator> dialogCreator = do_QueryInterface(mBrowserDOMWindow);
733 0 : while (!ShouldDelayDialogs() && mDelayedDialogs.Length()) {
734 0 : PRUint32 index = mDelayedDialogs.Length() - 1;
735 0 : DelayedDialogData* data = mDelayedDialogs[index];
736 0 : mDelayedDialogs.RemoveElementAt(index);
737 0 : nsCOMPtr<nsIDialogParamBlock> params;
738 0 : params.swap(data->mParams);
739 0 : PContentDialogParent* dialog = data->mDialog;
740 0 : if (dialogCreator) {
741 0 : dialogCreator->OpenDialog(data->mType,
742 : data->mName, data->mFeatures,
743 0 : params, mFrameElement);
744 0 : } else if (ww) {
745 0 : nsCAutoString url;
746 0 : if (data->mType) {
747 0 : if (data->mType == nsIDialogCreator::SELECT_DIALOG) {
748 0 : url.Assign("chrome://global/content/selectDialog.xul");
749 0 : } else if (data->mType == nsIDialogCreator::GENERIC_DIALOG) {
750 0 : url.Assign("chrome://global/content/commonDialog.xul");
751 : }
752 :
753 0 : nsCOMPtr<nsISupports> arguments(do_QueryInterface(params));
754 0 : nsCOMPtr<nsIDOMWindow> dialog;
755 0 : ww->OpenWindow(window, url.get(), data->mName.get(),
756 0 : data->mFeatures.get(), arguments, getter_AddRefs(dialog));
757 : } else {
758 0 : NS_WARNING("unknown dialog types aren't automatically supported in E10s yet!");
759 : }
760 : }
761 :
762 0 : delete data;
763 0 : if (dialog) {
764 0 : InfallibleTArray<PRInt32> intParams;
765 0 : InfallibleTArray<nsString> stringParams;
766 0 : TabChild::ParamsToArrays(params, intParams, stringParams);
767 : unused << PContentDialogParent::Send__delete__(dialog,
768 0 : intParams, stringParams);
769 : }
770 : }
771 0 : if (ShouldDelayDialogs() && mDelayedDialogs.Length()) {
772 0 : nsContentUtils::DispatchTrustedEvent(frame->OwnerDoc(), frame,
773 0 : NS_LITERAL_STRING("MozDelayedModalDialog"),
774 0 : true, true);
775 : }
776 0 : }
777 :
778 : PRenderFrameParent*
779 0 : TabParent::AllocPRenderFrame()
780 : {
781 0 : nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
782 0 : return new RenderFrameParent(frameLoader);
783 : }
784 :
785 : bool
786 0 : TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame)
787 : {
788 0 : delete aFrame;
789 0 : return true;
790 : }
791 :
792 : mozilla::docshell::POfflineCacheUpdateParent*
793 0 : TabParent::AllocPOfflineCacheUpdate(const URI& aManifestURI,
794 : const URI& aDocumentURI,
795 : const nsCString& aClientID,
796 : const bool& stickDocument)
797 : {
798 : nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
799 0 : new mozilla::docshell::OfflineCacheUpdateParent();
800 :
801 : nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aClientID,
802 0 : stickDocument);
803 0 : if (NS_FAILED(rv))
804 0 : return nsnull;
805 :
806 0 : POfflineCacheUpdateParent* result = update.get();
807 0 : update.forget();
808 0 : return result;
809 : }
810 :
811 : bool
812 0 : TabParent::DeallocPOfflineCacheUpdate(mozilla::docshell::POfflineCacheUpdateParent* actor)
813 : {
814 : mozilla::docshell::OfflineCacheUpdateParent* update =
815 0 : static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(actor);
816 :
817 0 : update->Release();
818 0 : return true;
819 : }
820 :
821 : bool
822 0 : TabParent::ShouldDelayDialogs()
823 : {
824 0 : nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
825 0 : NS_ENSURE_TRUE(frameLoader, true);
826 0 : bool delay = false;
827 0 : frameLoader->GetDelayRemoteDialogs(&delay);
828 0 : return delay;
829 : }
830 :
831 : bool
832 0 : TabParent::AllowContentIME()
833 : {
834 0 : nsFocusManager* fm = nsFocusManager::GetFocusManager();
835 0 : NS_ENSURE_TRUE(fm, false);
836 :
837 0 : nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
838 0 : if (focusedContent && focusedContent->IsEditable())
839 0 : return false;
840 :
841 0 : return true;
842 : }
843 :
844 : already_AddRefed<nsFrameLoader>
845 0 : TabParent::GetFrameLoader() const
846 : {
847 0 : nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(mFrameElement);
848 0 : return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nsnull;
849 : }
850 :
851 : already_AddRefed<nsIWidget>
852 0 : TabParent::GetWidget() const
853 : {
854 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
855 0 : if (!content)
856 0 : return nsnull;
857 :
858 0 : nsIFrame *frame = content->GetPrimaryFrame();
859 0 : if (!frame)
860 0 : return nsnull;
861 :
862 0 : return nsCOMPtr<nsIWidget>(frame->GetNearestWidget()).forget();
863 : }
864 :
865 : } // namespace tabs
866 : } // namespace mozilla
|