|
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 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "base/basictypes.h" |
|
8 |
|
9 #include "TabParent.h" |
|
10 |
|
11 #include "AppProcessChecker.h" |
|
12 #include "IDBFactory.h" |
|
13 #include "IndexedDBParent.h" |
|
14 #include "mozIApplication.h" |
|
15 #include "mozilla/BrowserElementParent.h" |
|
16 #include "mozilla/docshell/OfflineCacheUpdateParent.h" |
|
17 #include "mozilla/dom/ContentParent.h" |
|
18 #include "mozilla/dom/PContentPermissionRequestParent.h" |
|
19 #include "mozilla/EventStateManager.h" |
|
20 #include "mozilla/Hal.h" |
|
21 #include "mozilla/ipc/DocumentRendererParent.h" |
|
22 #include "mozilla/layers/CompositorParent.h" |
|
23 #include "mozilla/layout/RenderFrameParent.h" |
|
24 #include "mozilla/MouseEvents.h" |
|
25 #include "mozilla/Preferences.h" |
|
26 #include "mozilla/TextEvents.h" |
|
27 #include "mozilla/TouchEvents.h" |
|
28 #include "mozilla/unused.h" |
|
29 #include "nsCOMPtr.h" |
|
30 #include "nsContentPermissionHelper.h" |
|
31 #include "nsContentUtils.h" |
|
32 #include "nsDebug.h" |
|
33 #include "nsFocusManager.h" |
|
34 #include "nsFrameLoader.h" |
|
35 #include "nsIContent.h" |
|
36 #include "nsIDocShell.h" |
|
37 #include "nsIDocShellTreeOwner.h" |
|
38 #include "nsIDOMElement.h" |
|
39 #include "nsIDOMEvent.h" |
|
40 #include "nsIDOMWindow.h" |
|
41 #include "nsIDOMWindowUtils.h" |
|
42 #include "nsIInterfaceRequestorUtils.h" |
|
43 #include "nsIPromptFactory.h" |
|
44 #include "nsIURI.h" |
|
45 #include "nsIWebBrowserChrome.h" |
|
46 #include "nsIXULBrowserWindow.h" |
|
47 #include "nsIXULWindow.h" |
|
48 #include "nsViewManager.h" |
|
49 #include "nsIWidget.h" |
|
50 #include "nsIWindowWatcher.h" |
|
51 #include "nsPIDOMWindow.h" |
|
52 #include "nsPrintfCString.h" |
|
53 #include "nsServiceManagerUtils.h" |
|
54 #include "nsThreadUtils.h" |
|
55 #include "private/pprio.h" |
|
56 #include "PermissionMessageUtils.h" |
|
57 #include "StructuredCloneUtils.h" |
|
58 #include "ColorPickerParent.h" |
|
59 #include "JavaScriptParent.h" |
|
60 #include "FilePickerParent.h" |
|
61 #include "TabChild.h" |
|
62 #include "LoadContext.h" |
|
63 #include "nsNetCID.h" |
|
64 #include <algorithm> |
|
65 |
|
66 using namespace mozilla::dom; |
|
67 using namespace mozilla::ipc; |
|
68 using namespace mozilla::layers; |
|
69 using namespace mozilla::layout; |
|
70 using namespace mozilla::services; |
|
71 using namespace mozilla::widget; |
|
72 using namespace mozilla::dom::indexedDB; |
|
73 using namespace mozilla::jsipc; |
|
74 |
|
75 // The flags passed by the webProgress notifications are 16 bits shifted |
|
76 // from the ones registered by webProgressListeners. |
|
77 #define NOTIFY_FLAG_SHIFT 16 |
|
78 |
|
79 class OpenFileAndSendFDRunnable : public nsRunnable |
|
80 { |
|
81 const nsString mPath; |
|
82 nsRefPtr<TabParent> mTabParent; |
|
83 nsCOMPtr<nsIEventTarget> mEventTarget; |
|
84 PRFileDesc* mFD; |
|
85 |
|
86 public: |
|
87 OpenFileAndSendFDRunnable(const nsAString& aPath, TabParent* aTabParent) |
|
88 : mPath(aPath), mTabParent(aTabParent), mFD(nullptr) |
|
89 { |
|
90 MOZ_ASSERT(NS_IsMainThread()); |
|
91 MOZ_ASSERT(!aPath.IsEmpty()); |
|
92 MOZ_ASSERT(aTabParent); |
|
93 } |
|
94 |
|
95 void Dispatch() |
|
96 { |
|
97 MOZ_ASSERT(NS_IsMainThread()); |
|
98 |
|
99 mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); |
|
100 NS_ENSURE_TRUE_VOID(mEventTarget); |
|
101 |
|
102 nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL); |
|
103 NS_ENSURE_SUCCESS_VOID(rv); |
|
104 } |
|
105 |
|
106 private: |
|
107 ~OpenFileAndSendFDRunnable() |
|
108 { |
|
109 MOZ_ASSERT(!mFD); |
|
110 } |
|
111 |
|
112 // This shouldn't be called directly except by the event loop. Use Dispatch |
|
113 // to start the sequence. |
|
114 NS_IMETHOD Run() |
|
115 { |
|
116 if (NS_IsMainThread()) { |
|
117 SendResponse(); |
|
118 } else if (mFD) { |
|
119 CloseFile(); |
|
120 } else { |
|
121 OpenFile(); |
|
122 } |
|
123 |
|
124 return NS_OK; |
|
125 } |
|
126 |
|
127 void SendResponse() |
|
128 { |
|
129 MOZ_ASSERT(NS_IsMainThread()); |
|
130 MOZ_ASSERT(mTabParent); |
|
131 MOZ_ASSERT(mEventTarget); |
|
132 MOZ_ASSERT(mFD); |
|
133 |
|
134 nsRefPtr<TabParent> tabParent; |
|
135 mTabParent.swap(tabParent); |
|
136 |
|
137 using mozilla::ipc::FileDescriptor; |
|
138 |
|
139 FileDescriptor::PlatformHandleType handle = |
|
140 FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFD)); |
|
141 |
|
142 mozilla::unused << tabParent->SendCacheFileDescriptor(mPath, handle); |
|
143 |
|
144 nsCOMPtr<nsIEventTarget> eventTarget; |
|
145 mEventTarget.swap(eventTarget); |
|
146 |
|
147 if (NS_FAILED(eventTarget->Dispatch(this, NS_DISPATCH_NORMAL))) { |
|
148 NS_WARNING("Failed to dispatch to stream transport service!"); |
|
149 |
|
150 // It's probably safer to take the main thread IO hit here rather |
|
151 // than leak a file descriptor. |
|
152 CloseFile(); |
|
153 } |
|
154 } |
|
155 |
|
156 void OpenFile() |
|
157 { |
|
158 MOZ_ASSERT(!NS_IsMainThread()); |
|
159 MOZ_ASSERT(!mFD); |
|
160 |
|
161 nsCOMPtr<nsIFile> file; |
|
162 nsresult rv = NS_NewLocalFile(mPath, false, getter_AddRefs(file)); |
|
163 NS_ENSURE_SUCCESS_VOID(rv); |
|
164 |
|
165 PRFileDesc* fd; |
|
166 rv = file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd); |
|
167 NS_ENSURE_SUCCESS_VOID(rv); |
|
168 |
|
169 mFD = fd; |
|
170 |
|
171 if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { |
|
172 NS_WARNING("Failed to dispatch to main thread!"); |
|
173 |
|
174 CloseFile(); |
|
175 } |
|
176 } |
|
177 |
|
178 void CloseFile() |
|
179 { |
|
180 // It's possible for this to happen on the main thread if the dispatch |
|
181 // to the stream service fails after we've already opened the file so |
|
182 // we can't assert the thread we're running on. |
|
183 |
|
184 MOZ_ASSERT(mFD); |
|
185 |
|
186 PRStatus prrc; |
|
187 prrc = PR_Close(mFD); |
|
188 if (prrc != PR_SUCCESS) { |
|
189 NS_ERROR("PR_Close() failed."); |
|
190 } |
|
191 mFD = nullptr; |
|
192 } |
|
193 }; |
|
194 |
|
195 namespace mozilla { |
|
196 namespace dom { |
|
197 |
|
198 TabParent* sEventCapturer; |
|
199 |
|
200 TabParent *TabParent::mIMETabParent = nullptr; |
|
201 |
|
202 NS_IMPL_ISUPPORTS(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI) |
|
203 |
|
204 TabParent::TabParent(ContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags) |
|
205 : TabContext(aContext) |
|
206 , mFrameElement(nullptr) |
|
207 , mIMESelectionAnchor(0) |
|
208 , mIMESelectionFocus(0) |
|
209 , mIMEComposing(false) |
|
210 , mIMECompositionEnding(false) |
|
211 , mIMECompositionStart(0) |
|
212 , mIMESeqno(0) |
|
213 , mIMECompositionRectOffset(0) |
|
214 , mEventCaptureDepth(0) |
|
215 , mRect(0, 0, 0, 0) |
|
216 , mDimensions(0, 0) |
|
217 , mOrientation(0) |
|
218 , mDPI(0) |
|
219 , mDefaultScale(0) |
|
220 , mShown(false) |
|
221 , mUpdatedDimensions(false) |
|
222 , mManager(aManager) |
|
223 , mMarkedDestroying(false) |
|
224 , mIsDestroyed(false) |
|
225 , mAppPackageFileDescriptorSent(false) |
|
226 , mChromeFlags(aChromeFlags) |
|
227 { |
|
228 } |
|
229 |
|
230 TabParent::~TabParent() |
|
231 { |
|
232 } |
|
233 |
|
234 void |
|
235 TabParent::SetOwnerElement(Element* aElement) |
|
236 { |
|
237 mFrameElement = aElement; |
|
238 TryCacheDPIAndScale(); |
|
239 } |
|
240 |
|
241 void |
|
242 TabParent::GetAppType(nsAString& aOut) |
|
243 { |
|
244 aOut.Truncate(); |
|
245 nsCOMPtr<Element> elem = do_QueryInterface(mFrameElement); |
|
246 if (!elem) { |
|
247 return; |
|
248 } |
|
249 |
|
250 elem->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, aOut); |
|
251 } |
|
252 |
|
253 bool |
|
254 TabParent::IsVisible() |
|
255 { |
|
256 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
257 if (!frameLoader) { |
|
258 return false; |
|
259 } |
|
260 |
|
261 bool visible = false; |
|
262 frameLoader->GetVisible(&visible); |
|
263 return visible; |
|
264 } |
|
265 |
|
266 void |
|
267 TabParent::Destroy() |
|
268 { |
|
269 if (mIsDestroyed) { |
|
270 return; |
|
271 } |
|
272 |
|
273 // If this fails, it's most likely due to a content-process crash, |
|
274 // and auto-cleanup will kick in. Otherwise, the child side will |
|
275 // destroy itself and send back __delete__(). |
|
276 unused << SendDestroy(); |
|
277 |
|
278 const InfallibleTArray<PIndexedDBParent*>& idbParents = |
|
279 ManagedPIndexedDBParent(); |
|
280 for (uint32_t i = 0; i < idbParents.Length(); ++i) { |
|
281 static_cast<IndexedDBParent*>(idbParents[i])->Disconnect(); |
|
282 } |
|
283 |
|
284 const InfallibleTArray<POfflineCacheUpdateParent*>& ocuParents = |
|
285 ManagedPOfflineCacheUpdateParent(); |
|
286 for (uint32_t i = 0; i < ocuParents.Length(); ++i) { |
|
287 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> ocuParent = |
|
288 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(ocuParents[i]); |
|
289 ocuParent->StopSendingMessagesToChild(); |
|
290 } |
|
291 |
|
292 if (RenderFrameParent* frame = GetRenderFrame()) { |
|
293 frame->Destroy(); |
|
294 } |
|
295 mIsDestroyed = true; |
|
296 |
|
297 Manager()->NotifyTabDestroying(this); |
|
298 mMarkedDestroying = true; |
|
299 } |
|
300 |
|
301 bool |
|
302 TabParent::Recv__delete__() |
|
303 { |
|
304 Manager()->NotifyTabDestroyed(this, mMarkedDestroying); |
|
305 return true; |
|
306 } |
|
307 |
|
308 void |
|
309 TabParent::ActorDestroy(ActorDestroyReason why) |
|
310 { |
|
311 if (sEventCapturer == this) { |
|
312 sEventCapturer = nullptr; |
|
313 } |
|
314 if (mIMETabParent == this) { |
|
315 mIMETabParent = nullptr; |
|
316 } |
|
317 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
318 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); |
|
319 nsRefPtr<nsFrameMessageManager> fmm; |
|
320 if (frameLoader) { |
|
321 fmm = frameLoader->GetFrameMessageManager(); |
|
322 nsCOMPtr<Element> frameElement(mFrameElement); |
|
323 ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr, |
|
324 nullptr); |
|
325 frameLoader->DestroyChild(); |
|
326 |
|
327 if (why == AbnormalShutdown && os) { |
|
328 os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader), |
|
329 "oop-frameloader-crashed", nullptr); |
|
330 nsContentUtils::DispatchTrustedEvent(frameElement->OwnerDoc(), frameElement, |
|
331 NS_LITERAL_STRING("oop-browser-crashed"), |
|
332 true, true); |
|
333 } |
|
334 } |
|
335 |
|
336 if (os) { |
|
337 os->NotifyObservers(NS_ISUPPORTS_CAST(nsITabParent*, this), "ipc:browser-destroyed", nullptr); |
|
338 } |
|
339 if (fmm) { |
|
340 fmm->Disconnect(); |
|
341 } |
|
342 } |
|
343 |
|
344 bool |
|
345 TabParent::RecvMoveFocus(const bool& aForward) |
|
346 { |
|
347 nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); |
|
348 if (fm) { |
|
349 nsCOMPtr<nsIDOMElement> dummy; |
|
350 uint32_t type = aForward ? uint32_t(nsIFocusManager::MOVEFOCUS_FORWARD) |
|
351 : uint32_t(nsIFocusManager::MOVEFOCUS_BACKWARD); |
|
352 nsCOMPtr<nsIDOMElement> frame = do_QueryInterface(mFrameElement); |
|
353 fm->MoveFocus(nullptr, frame, type, nsIFocusManager::FLAG_BYKEY, |
|
354 getter_AddRefs(dummy)); |
|
355 } |
|
356 return true; |
|
357 } |
|
358 |
|
359 bool |
|
360 TabParent::RecvEvent(const RemoteDOMEvent& aEvent) |
|
361 { |
|
362 nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(aEvent.mEvent); |
|
363 NS_ENSURE_TRUE(event, true); |
|
364 |
|
365 nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement); |
|
366 NS_ENSURE_TRUE(target, true); |
|
367 |
|
368 event->SetOwner(target); |
|
369 |
|
370 bool dummy; |
|
371 target->DispatchEvent(event, &dummy); |
|
372 return true; |
|
373 } |
|
374 |
|
375 bool |
|
376 TabParent::AnswerCreateWindow(PBrowserParent** retval) |
|
377 { |
|
378 if (!mBrowserDOMWindow) { |
|
379 return false; |
|
380 } |
|
381 |
|
382 // Only non-app, non-browser processes may call CreateWindow. |
|
383 if (IsBrowserOrApp()) { |
|
384 return false; |
|
385 } |
|
386 |
|
387 // Get a new rendering area from the browserDOMWin. We don't want |
|
388 // to be starting any loads here, so get it with a null URI. |
|
389 nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner; |
|
390 mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr, |
|
391 nsIBrowserDOMWindow::OPEN_NEWTAB, |
|
392 nsIBrowserDOMWindow::OPEN_NEW, |
|
393 getter_AddRefs(frameLoaderOwner)); |
|
394 if (!frameLoaderOwner) { |
|
395 return false; |
|
396 } |
|
397 |
|
398 nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); |
|
399 if (!frameLoader) { |
|
400 return false; |
|
401 } |
|
402 |
|
403 *retval = frameLoader->GetRemoteBrowser(); |
|
404 return true; |
|
405 } |
|
406 |
|
407 void |
|
408 TabParent::LoadURL(nsIURI* aURI) |
|
409 { |
|
410 MOZ_ASSERT(aURI); |
|
411 |
|
412 if (mIsDestroyed) { |
|
413 return; |
|
414 } |
|
415 |
|
416 nsCString spec; |
|
417 aURI->GetSpec(spec); |
|
418 |
|
419 if (!mShown) { |
|
420 NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before " |
|
421 "Show(). Ignoring LoadURL.\n", |
|
422 spec.get()).get()); |
|
423 return; |
|
424 } |
|
425 |
|
426 unused << SendLoadURL(spec); |
|
427 |
|
428 // If this app is a packaged app then we can speed startup by sending over |
|
429 // the file descriptor for the "application.zip" file that it will |
|
430 // invariably request. Only do this once. |
|
431 if (!mAppPackageFileDescriptorSent) { |
|
432 mAppPackageFileDescriptorSent = true; |
|
433 |
|
434 nsCOMPtr<mozIApplication> app = GetOwnOrContainingApp(); |
|
435 if (app) { |
|
436 nsString manifestURL; |
|
437 nsresult rv = app->GetManifestURL(manifestURL); |
|
438 NS_ENSURE_SUCCESS_VOID(rv); |
|
439 |
|
440 if (StringBeginsWith(manifestURL, NS_LITERAL_STRING("app:"))) { |
|
441 nsString basePath; |
|
442 rv = app->GetBasePath(basePath); |
|
443 NS_ENSURE_SUCCESS_VOID(rv); |
|
444 |
|
445 nsString appId; |
|
446 rv = app->GetId(appId); |
|
447 NS_ENSURE_SUCCESS_VOID(rv); |
|
448 |
|
449 nsCOMPtr<nsIFile> packageFile; |
|
450 rv = NS_NewLocalFile(basePath, false, |
|
451 getter_AddRefs(packageFile)); |
|
452 NS_ENSURE_SUCCESS_VOID(rv); |
|
453 |
|
454 rv = packageFile->Append(appId); |
|
455 NS_ENSURE_SUCCESS_VOID(rv); |
|
456 |
|
457 rv = packageFile->Append(NS_LITERAL_STRING("application.zip")); |
|
458 NS_ENSURE_SUCCESS_VOID(rv); |
|
459 |
|
460 nsString path; |
|
461 rv = packageFile->GetPath(path); |
|
462 NS_ENSURE_SUCCESS_VOID(rv); |
|
463 |
|
464 nsRefPtr<OpenFileAndSendFDRunnable> openFileRunnable = |
|
465 new OpenFileAndSendFDRunnable(path, this); |
|
466 openFileRunnable->Dispatch(); |
|
467 } |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 void |
|
473 TabParent::Show(const nsIntSize& size) |
|
474 { |
|
475 // sigh |
|
476 mShown = true; |
|
477 mDimensions = size; |
|
478 if (!mIsDestroyed) { |
|
479 unused << SendShow(size); |
|
480 } |
|
481 } |
|
482 |
|
483 void |
|
484 TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size) |
|
485 { |
|
486 if (mIsDestroyed) { |
|
487 return; |
|
488 } |
|
489 hal::ScreenConfiguration config; |
|
490 hal::GetCurrentScreenConfiguration(&config); |
|
491 ScreenOrientation orientation = config.orientation(); |
|
492 |
|
493 if (!mUpdatedDimensions || mOrientation != orientation || |
|
494 mDimensions != size || !mRect.IsEqualEdges(rect)) { |
|
495 mUpdatedDimensions = true; |
|
496 mRect = rect; |
|
497 mDimensions = size; |
|
498 mOrientation = orientation; |
|
499 |
|
500 unused << SendUpdateDimensions(mRect, mDimensions, mOrientation); |
|
501 } |
|
502 } |
|
503 |
|
504 void |
|
505 TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics) |
|
506 { |
|
507 if (!mIsDestroyed) { |
|
508 unused << SendUpdateFrame(aFrameMetrics); |
|
509 } |
|
510 } |
|
511 |
|
512 void |
|
513 TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration) |
|
514 { |
|
515 if (!mIsDestroyed) { |
|
516 unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration); |
|
517 } |
|
518 } |
|
519 |
|
520 void TabParent::HandleDoubleTap(const CSSPoint& aPoint, |
|
521 int32_t aModifiers, |
|
522 const ScrollableLayerGuid &aGuid) |
|
523 { |
|
524 if (!mIsDestroyed) { |
|
525 unused << SendHandleDoubleTap(aPoint, aGuid); |
|
526 } |
|
527 } |
|
528 |
|
529 void TabParent::HandleSingleTap(const CSSPoint& aPoint, |
|
530 int32_t aModifiers, |
|
531 const ScrollableLayerGuid &aGuid) |
|
532 { |
|
533 // TODO Send the modifier data to TabChild for use in mouse events. |
|
534 if (!mIsDestroyed) { |
|
535 unused << SendHandleSingleTap(aPoint, aGuid); |
|
536 } |
|
537 } |
|
538 |
|
539 void TabParent::HandleLongTap(const CSSPoint& aPoint, |
|
540 int32_t aModifiers, |
|
541 const ScrollableLayerGuid &aGuid) |
|
542 { |
|
543 if (!mIsDestroyed) { |
|
544 unused << SendHandleLongTap(aPoint, aGuid); |
|
545 } |
|
546 } |
|
547 |
|
548 void TabParent::HandleLongTapUp(const CSSPoint& aPoint, |
|
549 int32_t aModifiers, |
|
550 const ScrollableLayerGuid &aGuid) |
|
551 { |
|
552 if (!mIsDestroyed) { |
|
553 unused << SendHandleLongTapUp(aPoint, aGuid); |
|
554 } |
|
555 } |
|
556 |
|
557 void TabParent::NotifyAPZStateChange(ViewID aViewId, |
|
558 APZStateChange aChange, |
|
559 int aArg) |
|
560 { |
|
561 if (!mIsDestroyed) { |
|
562 unused << SendNotifyAPZStateChange(aViewId, aChange, aArg); |
|
563 } |
|
564 } |
|
565 |
|
566 void |
|
567 TabParent::Activate() |
|
568 { |
|
569 if (!mIsDestroyed) { |
|
570 unused << SendActivate(); |
|
571 } |
|
572 } |
|
573 |
|
574 void |
|
575 TabParent::Deactivate() |
|
576 { |
|
577 if (!mIsDestroyed) { |
|
578 unused << SendDeactivate(); |
|
579 } |
|
580 } |
|
581 |
|
582 NS_IMETHODIMP |
|
583 TabParent::Init(nsIDOMWindow *window) |
|
584 { |
|
585 return NS_OK; |
|
586 } |
|
587 |
|
588 NS_IMETHODIMP |
|
589 TabParent::GetState(uint32_t *aState) |
|
590 { |
|
591 NS_ENSURE_ARG(aState); |
|
592 NS_WARNING("SecurityState not valid here"); |
|
593 *aState = 0; |
|
594 return NS_OK; |
|
595 } |
|
596 |
|
597 NS_IMETHODIMP |
|
598 TabParent::SetDocShell(nsIDocShell *aDocShell) |
|
599 { |
|
600 NS_ENSURE_ARG(aDocShell); |
|
601 NS_WARNING("No mDocShell member in TabParent so there is no docShell to set"); |
|
602 return NS_OK; |
|
603 } |
|
604 |
|
605 PDocumentRendererParent* |
|
606 TabParent::AllocPDocumentRendererParent(const nsRect& documentRect, |
|
607 const gfx::Matrix& transform, |
|
608 const nsString& bgcolor, |
|
609 const uint32_t& renderFlags, |
|
610 const bool& flushLayout, |
|
611 const nsIntSize& renderSize) |
|
612 { |
|
613 return new DocumentRendererParent(); |
|
614 } |
|
615 |
|
616 bool |
|
617 TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor) |
|
618 { |
|
619 delete actor; |
|
620 return true; |
|
621 } |
|
622 |
|
623 PContentPermissionRequestParent* |
|
624 TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests, |
|
625 const IPC::Principal& aPrincipal) |
|
626 { |
|
627 return CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal); |
|
628 } |
|
629 |
|
630 bool |
|
631 TabParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) |
|
632 { |
|
633 delete actor; |
|
634 return true; |
|
635 } |
|
636 |
|
637 PFilePickerParent* |
|
638 TabParent::AllocPFilePickerParent(const nsString& aTitle, const int16_t& aMode) |
|
639 { |
|
640 return new FilePickerParent(aTitle, aMode); |
|
641 } |
|
642 |
|
643 bool |
|
644 TabParent::DeallocPFilePickerParent(PFilePickerParent* actor) |
|
645 { |
|
646 delete actor; |
|
647 return true; |
|
648 } |
|
649 |
|
650 void |
|
651 TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY, |
|
652 int32_t aButton, int32_t aClickCount, |
|
653 int32_t aModifiers, bool aIgnoreRootScrollFrame) |
|
654 { |
|
655 if (!mIsDestroyed) { |
|
656 unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY, |
|
657 aButton, aClickCount, |
|
658 aModifiers, aIgnoreRootScrollFrame); |
|
659 } |
|
660 } |
|
661 |
|
662 void |
|
663 TabParent::SendKeyEvent(const nsAString& aType, |
|
664 int32_t aKeyCode, |
|
665 int32_t aCharCode, |
|
666 int32_t aModifiers, |
|
667 bool aPreventDefault) |
|
668 { |
|
669 if (!mIsDestroyed) { |
|
670 unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode, |
|
671 aModifiers, aPreventDefault); |
|
672 } |
|
673 } |
|
674 |
|
675 bool |
|
676 TabParent::MapEventCoordinatesForChildProcess(WidgetEvent* aEvent) |
|
677 { |
|
678 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
679 if (!frameLoader) { |
|
680 return false; |
|
681 } |
|
682 LayoutDeviceIntPoint offset = |
|
683 EventStateManager::GetChildProcessOffset(frameLoader, *aEvent); |
|
684 MapEventCoordinatesForChildProcess(offset, aEvent); |
|
685 return true; |
|
686 } |
|
687 |
|
688 void |
|
689 TabParent::MapEventCoordinatesForChildProcess( |
|
690 const LayoutDeviceIntPoint& aOffset, WidgetEvent* aEvent) |
|
691 { |
|
692 if (aEvent->eventStructType != NS_TOUCH_EVENT) { |
|
693 aEvent->refPoint = aOffset; |
|
694 } else { |
|
695 aEvent->refPoint = LayoutDeviceIntPoint(); |
|
696 // Then offset all the touch points by that distance, to put them |
|
697 // in the space where top-left is 0,0. |
|
698 const nsTArray< nsRefPtr<Touch> >& touches = |
|
699 aEvent->AsTouchEvent()->touches; |
|
700 for (uint32_t i = 0; i < touches.Length(); ++i) { |
|
701 Touch* touch = touches[i]; |
|
702 if (touch) { |
|
703 touch->mRefPoint += LayoutDeviceIntPoint::ToUntyped(aOffset); |
|
704 } |
|
705 } |
|
706 } |
|
707 } |
|
708 |
|
709 bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event) |
|
710 { |
|
711 if (mIsDestroyed) { |
|
712 return false; |
|
713 } |
|
714 MaybeForwardEventToRenderFrame(event, nullptr); |
|
715 if (!MapEventCoordinatesForChildProcess(&event)) { |
|
716 return false; |
|
717 } |
|
718 return PBrowserParent::SendRealMouseEvent(event); |
|
719 } |
|
720 |
|
721 CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint) |
|
722 { |
|
723 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement); |
|
724 |
|
725 if (!content || !content->OwnerDoc()) { |
|
726 return aPoint; |
|
727 } |
|
728 |
|
729 nsIDocument* doc = content->OwnerDoc(); |
|
730 if (!doc || !doc->GetShell()) { |
|
731 return aPoint; |
|
732 } |
|
733 nsPresContext* presContext = doc->GetShell()->GetPresContext(); |
|
734 |
|
735 return aPoint + CSSPoint( |
|
736 presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.x), |
|
737 presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.y)); |
|
738 } |
|
739 |
|
740 bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
741 { |
|
742 if (mIsDestroyed) { |
|
743 return false; |
|
744 } |
|
745 |
|
746 return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aGuid); |
|
747 } |
|
748 |
|
749 bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
750 { |
|
751 if (mIsDestroyed) { |
|
752 return false; |
|
753 } |
|
754 |
|
755 return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aGuid); |
|
756 } |
|
757 |
|
758 bool TabParent::SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
759 { |
|
760 if (mIsDestroyed) { |
|
761 return false; |
|
762 } |
|
763 |
|
764 return PBrowserParent::SendHandleLongTapUp(AdjustTapToChildWidget(aPoint), aGuid); |
|
765 } |
|
766 |
|
767 bool TabParent::SendHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
768 { |
|
769 if (mIsDestroyed) { |
|
770 return false; |
|
771 } |
|
772 |
|
773 return PBrowserParent::SendHandleDoubleTap(AdjustTapToChildWidget(aPoint), aGuid); |
|
774 } |
|
775 |
|
776 bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event) |
|
777 { |
|
778 if (mIsDestroyed) { |
|
779 return false; |
|
780 } |
|
781 MaybeForwardEventToRenderFrame(event, nullptr); |
|
782 if (!MapEventCoordinatesForChildProcess(&event)) { |
|
783 return false; |
|
784 } |
|
785 return PBrowserParent::SendMouseWheelEvent(event); |
|
786 } |
|
787 |
|
788 static void |
|
789 DoCommandCallback(mozilla::Command aCommand, void* aData) |
|
790 { |
|
791 static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->AppendElement(aCommand); |
|
792 } |
|
793 |
|
794 bool |
|
795 TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent, |
|
796 MaybeNativeKeyBinding* aBindings) |
|
797 { |
|
798 AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine; |
|
799 AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine; |
|
800 AutoInfallibleTArray<mozilla::CommandInt, 4> richText; |
|
801 |
|
802 *aBindings = mozilla::void_t(); |
|
803 |
|
804 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
805 if (!widget) { |
|
806 return true; |
|
807 } |
|
808 |
|
809 WidgetKeyboardEvent localEvent(aEvent); |
|
810 |
|
811 if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) { |
|
812 return true; |
|
813 } |
|
814 |
|
815 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor, |
|
816 localEvent, DoCommandCallback, &singleLine); |
|
817 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor, |
|
818 localEvent, DoCommandCallback, &multiLine); |
|
819 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor, |
|
820 localEvent, DoCommandCallback, &richText); |
|
821 |
|
822 if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) { |
|
823 *aBindings = NativeKeyBinding(singleLine, multiLine, richText); |
|
824 } |
|
825 |
|
826 return true; |
|
827 } |
|
828 |
|
829 bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event) |
|
830 { |
|
831 if (mIsDestroyed) { |
|
832 return false; |
|
833 } |
|
834 MaybeForwardEventToRenderFrame(event, nullptr); |
|
835 if (!MapEventCoordinatesForChildProcess(&event)) { |
|
836 return false; |
|
837 } |
|
838 |
|
839 |
|
840 MaybeNativeKeyBinding bindings; |
|
841 bindings = void_t(); |
|
842 if (event.message == NS_KEY_PRESS) { |
|
843 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
844 |
|
845 AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine; |
|
846 AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine; |
|
847 AutoInfallibleTArray<mozilla::CommandInt, 4> richText; |
|
848 |
|
849 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor, |
|
850 event, DoCommandCallback, &singleLine); |
|
851 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor, |
|
852 event, DoCommandCallback, &multiLine); |
|
853 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor, |
|
854 event, DoCommandCallback, &richText); |
|
855 |
|
856 if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) { |
|
857 bindings = NativeKeyBinding(singleLine, multiLine, richText); |
|
858 } |
|
859 } |
|
860 |
|
861 return PBrowserParent::SendRealKeyEvent(event, bindings); |
|
862 } |
|
863 |
|
864 bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event) |
|
865 { |
|
866 if (mIsDestroyed) { |
|
867 return false; |
|
868 } |
|
869 if (event.message == NS_TOUCH_START) { |
|
870 // Adjust the widget coordinates to be relative to our frame. |
|
871 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
872 if (!frameLoader) { |
|
873 // No frame anymore? |
|
874 sEventCapturer = nullptr; |
|
875 return false; |
|
876 } |
|
877 |
|
878 mChildProcessOffsetAtTouchStart = |
|
879 EventStateManager::GetChildProcessOffset(frameLoader, event); |
|
880 |
|
881 MOZ_ASSERT((!sEventCapturer && mEventCaptureDepth == 0) || |
|
882 (sEventCapturer == this && mEventCaptureDepth > 0)); |
|
883 // We want to capture all remaining touch events in this series |
|
884 // for fast-path dispatch. |
|
885 sEventCapturer = this; |
|
886 ++mEventCaptureDepth; |
|
887 } |
|
888 |
|
889 // PresShell::HandleEventInternal adds touches on touch end/cancel. This |
|
890 // confuses remote content and the panning and zooming logic into thinking |
|
891 // that the added touches are part of the touchend/cancel, when actually |
|
892 // they're not. |
|
893 if (event.message == NS_TOUCH_END || event.message == NS_TOUCH_CANCEL) { |
|
894 for (int i = event.touches.Length() - 1; i >= 0; i--) { |
|
895 if (!event.touches[i]->mChanged) { |
|
896 event.touches.RemoveElementAt(i); |
|
897 } |
|
898 } |
|
899 } |
|
900 |
|
901 ScrollableLayerGuid guid; |
|
902 MaybeForwardEventToRenderFrame(event, &guid); |
|
903 |
|
904 if (mIsDestroyed) { |
|
905 return false; |
|
906 } |
|
907 |
|
908 MapEventCoordinatesForChildProcess(mChildProcessOffsetAtTouchStart, &event); |
|
909 |
|
910 return (event.message == NS_TOUCH_MOVE) ? |
|
911 PBrowserParent::SendRealTouchMoveEvent(event, guid) : |
|
912 PBrowserParent::SendRealTouchEvent(event, guid); |
|
913 } |
|
914 |
|
915 /*static*/ TabParent* |
|
916 TabParent::GetEventCapturer() |
|
917 { |
|
918 return sEventCapturer; |
|
919 } |
|
920 |
|
921 bool |
|
922 TabParent::TryCapture(const WidgetGUIEvent& aEvent) |
|
923 { |
|
924 MOZ_ASSERT(sEventCapturer == this && mEventCaptureDepth > 0); |
|
925 |
|
926 if (aEvent.eventStructType != NS_TOUCH_EVENT) { |
|
927 // Only capture of touch events is implemented, for now. |
|
928 return false; |
|
929 } |
|
930 |
|
931 WidgetTouchEvent event(*aEvent.AsTouchEvent()); |
|
932 |
|
933 bool isTouchPointUp = (event.message == NS_TOUCH_END || |
|
934 event.message == NS_TOUCH_CANCEL); |
|
935 if (event.message == NS_TOUCH_START || isTouchPointUp) { |
|
936 // Let the DOM see touch start/end events so that its touch-point |
|
937 // state stays consistent. |
|
938 if (isTouchPointUp && 0 == --mEventCaptureDepth) { |
|
939 // All event series are un-captured, don't try to catch any |
|
940 // more. |
|
941 sEventCapturer = nullptr; |
|
942 } |
|
943 return false; |
|
944 } |
|
945 |
|
946 SendRealTouchEvent(event); |
|
947 return true; |
|
948 } |
|
949 |
|
950 bool |
|
951 TabParent::RecvSyncMessage(const nsString& aMessage, |
|
952 const ClonedMessageData& aData, |
|
953 const InfallibleTArray<CpowEntry>& aCpows, |
|
954 const IPC::Principal& aPrincipal, |
|
955 InfallibleTArray<nsString>* aJSONRetVal) |
|
956 { |
|
957 nsIPrincipal* principal = aPrincipal; |
|
958 ContentParent* parent = static_cast<ContentParent*>(Manager()); |
|
959 if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) && |
|
960 principal && !AssertAppPrincipal(parent, principal)) { |
|
961 return false; |
|
962 } |
|
963 |
|
964 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); |
|
965 CpowIdHolder cpows(parent->GetCPOWManager(), aCpows); |
|
966 return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal); |
|
967 } |
|
968 |
|
969 bool |
|
970 TabParent::AnswerRpcMessage(const nsString& aMessage, |
|
971 const ClonedMessageData& aData, |
|
972 const InfallibleTArray<CpowEntry>& aCpows, |
|
973 const IPC::Principal& aPrincipal, |
|
974 InfallibleTArray<nsString>* aJSONRetVal) |
|
975 { |
|
976 nsIPrincipal* principal = aPrincipal; |
|
977 ContentParent* parent = static_cast<ContentParent*>(Manager()); |
|
978 if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) && |
|
979 principal && !AssertAppPrincipal(parent, principal)) { |
|
980 return false; |
|
981 } |
|
982 |
|
983 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); |
|
984 CpowIdHolder cpows(parent->GetCPOWManager(), aCpows); |
|
985 return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal); |
|
986 } |
|
987 |
|
988 bool |
|
989 TabParent::RecvAsyncMessage(const nsString& aMessage, |
|
990 const ClonedMessageData& aData, |
|
991 const InfallibleTArray<CpowEntry>& aCpows, |
|
992 const IPC::Principal& aPrincipal) |
|
993 { |
|
994 nsIPrincipal* principal = aPrincipal; |
|
995 ContentParent* parent = static_cast<ContentParent*>(Manager()); |
|
996 if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) && |
|
997 principal && !AssertAppPrincipal(parent, principal)) { |
|
998 return false; |
|
999 } |
|
1000 |
|
1001 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); |
|
1002 CpowIdHolder cpows(parent->GetCPOWManager(), aCpows); |
|
1003 return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); |
|
1004 } |
|
1005 |
|
1006 bool |
|
1007 TabParent::RecvSetCursor(const uint32_t& aCursor) |
|
1008 { |
|
1009 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1010 if (widget) { |
|
1011 widget->SetCursor((nsCursor) aCursor); |
|
1012 } |
|
1013 return true; |
|
1014 } |
|
1015 |
|
1016 bool |
|
1017 TabParent::RecvSetBackgroundColor(const nscolor& aColor) |
|
1018 { |
|
1019 if (RenderFrameParent* frame = GetRenderFrame()) { |
|
1020 frame->SetBackgroundColor(aColor); |
|
1021 } |
|
1022 return true; |
|
1023 } |
|
1024 |
|
1025 nsIXULBrowserWindow* |
|
1026 TabParent::GetXULBrowserWindow() |
|
1027 { |
|
1028 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement); |
|
1029 if (!frame) { |
|
1030 return nullptr; |
|
1031 } |
|
1032 |
|
1033 nsCOMPtr<nsIDocShell> docShell = frame->OwnerDoc()->GetDocShell(); |
|
1034 if (!docShell) { |
|
1035 return nullptr; |
|
1036 } |
|
1037 |
|
1038 nsCOMPtr<nsIDocShellTreeOwner> treeOwner; |
|
1039 docShell->GetTreeOwner(getter_AddRefs(treeOwner)); |
|
1040 if (!treeOwner) { |
|
1041 return nullptr; |
|
1042 } |
|
1043 |
|
1044 nsCOMPtr<nsIXULWindow> window = do_GetInterface(treeOwner); |
|
1045 if (!window) { |
|
1046 return nullptr; |
|
1047 } |
|
1048 |
|
1049 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow; |
|
1050 window->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); |
|
1051 return xulBrowserWindow; |
|
1052 } |
|
1053 |
|
1054 bool |
|
1055 TabParent::RecvSetStatus(const uint32_t& aType, const nsString& aStatus) |
|
1056 { |
|
1057 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow(); |
|
1058 if (!xulBrowserWindow) { |
|
1059 return true; |
|
1060 } |
|
1061 |
|
1062 switch (aType) { |
|
1063 case nsIWebBrowserChrome::STATUS_SCRIPT: |
|
1064 xulBrowserWindow->SetJSStatus(aStatus); |
|
1065 break; |
|
1066 case nsIWebBrowserChrome::STATUS_LINK: |
|
1067 xulBrowserWindow->SetOverLink(aStatus, nullptr); |
|
1068 break; |
|
1069 } |
|
1070 return true; |
|
1071 } |
|
1072 |
|
1073 bool |
|
1074 TabParent::RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip) |
|
1075 { |
|
1076 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow(); |
|
1077 if (!xulBrowserWindow) { |
|
1078 return true; |
|
1079 } |
|
1080 |
|
1081 xulBrowserWindow->ShowTooltip(aX, aY, aTooltip); |
|
1082 return true; |
|
1083 } |
|
1084 |
|
1085 bool |
|
1086 TabParent::RecvHideTooltip() |
|
1087 { |
|
1088 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow(); |
|
1089 if (!xulBrowserWindow) { |
|
1090 return true; |
|
1091 } |
|
1092 |
|
1093 xulBrowserWindow->HideTooltip(); |
|
1094 return true; |
|
1095 } |
|
1096 |
|
1097 bool |
|
1098 TabParent::RecvNotifyIMEFocus(const bool& aFocus, |
|
1099 nsIMEUpdatePreference* aPreference, |
|
1100 uint32_t* aSeqno) |
|
1101 { |
|
1102 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1103 if (!widget) { |
|
1104 *aPreference = nsIMEUpdatePreference(); |
|
1105 return true; |
|
1106 } |
|
1107 |
|
1108 *aSeqno = mIMESeqno; |
|
1109 mIMETabParent = aFocus ? this : nullptr; |
|
1110 mIMESelectionAnchor = 0; |
|
1111 mIMESelectionFocus = 0; |
|
1112 widget->NotifyIME(IMENotification(aFocus ? NOTIFY_IME_OF_FOCUS : |
|
1113 NOTIFY_IME_OF_BLUR)); |
|
1114 |
|
1115 if (aFocus) { |
|
1116 *aPreference = widget->GetIMEUpdatePreference(); |
|
1117 } else { |
|
1118 mIMECacheText.Truncate(0); |
|
1119 } |
|
1120 return true; |
|
1121 } |
|
1122 |
|
1123 bool |
|
1124 TabParent::RecvNotifyIMETextChange(const uint32_t& aStart, |
|
1125 const uint32_t& aEnd, |
|
1126 const uint32_t& aNewEnd, |
|
1127 const bool& aCausedByComposition) |
|
1128 { |
|
1129 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1130 if (!widget) |
|
1131 return true; |
|
1132 |
|
1133 #ifdef DEBUG |
|
1134 nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference(); |
|
1135 NS_ASSERTION(updatePreference.WantTextChange(), |
|
1136 "Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE"); |
|
1137 MOZ_ASSERT(!aCausedByComposition || |
|
1138 updatePreference.WantChangesCausedByComposition(), |
|
1139 "The widget doesn't want text change notification caused by composition"); |
|
1140 #endif |
|
1141 |
|
1142 IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE); |
|
1143 notification.mTextChangeData.mStartOffset = aStart; |
|
1144 notification.mTextChangeData.mOldEndOffset = aEnd; |
|
1145 notification.mTextChangeData.mNewEndOffset = aNewEnd; |
|
1146 notification.mTextChangeData.mCausedByComposition = aCausedByComposition; |
|
1147 widget->NotifyIME(notification); |
|
1148 return true; |
|
1149 } |
|
1150 |
|
1151 bool |
|
1152 TabParent::RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset, |
|
1153 const nsIntRect& aRect, |
|
1154 const nsIntRect& aCaretRect) |
|
1155 { |
|
1156 // add rect to cache for another query |
|
1157 mIMECompositionRectOffset = aOffset; |
|
1158 mIMECompositionRect = aRect; |
|
1159 mIMECaretRect = aCaretRect; |
|
1160 |
|
1161 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1162 if (!widget) { |
|
1163 return true; |
|
1164 } |
|
1165 widget->NotifyIME(IMENotification(NOTIFY_IME_OF_COMPOSITION_UPDATE)); |
|
1166 return true; |
|
1167 } |
|
1168 |
|
1169 bool |
|
1170 TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno, |
|
1171 const uint32_t& aAnchor, |
|
1172 const uint32_t& aFocus, |
|
1173 const bool& aCausedByComposition) |
|
1174 { |
|
1175 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1176 if (!widget) |
|
1177 return true; |
|
1178 |
|
1179 if (aSeqno == mIMESeqno) { |
|
1180 mIMESelectionAnchor = aAnchor; |
|
1181 mIMESelectionFocus = aFocus; |
|
1182 const nsIMEUpdatePreference updatePreference = |
|
1183 widget->GetIMEUpdatePreference(); |
|
1184 if (updatePreference.WantSelectionChange() && |
|
1185 (updatePreference.WantChangesCausedByComposition() || |
|
1186 !aCausedByComposition)) { |
|
1187 IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE); |
|
1188 notification.mSelectionChangeData.mCausedByComposition = |
|
1189 aCausedByComposition; |
|
1190 widget->NotifyIME(notification); |
|
1191 } |
|
1192 } |
|
1193 return true; |
|
1194 } |
|
1195 |
|
1196 bool |
|
1197 TabParent::RecvNotifyIMETextHint(const nsString& aText) |
|
1198 { |
|
1199 // Replace our cache with new text |
|
1200 mIMECacheText = aText; |
|
1201 return true; |
|
1202 } |
|
1203 |
|
1204 bool |
|
1205 TabParent::RecvRequestFocus(const bool& aCanRaise) |
|
1206 { |
|
1207 nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager(); |
|
1208 if (!fm) { |
|
1209 return true; |
|
1210 } |
|
1211 |
|
1212 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement); |
|
1213 if (!content || !content->OwnerDoc()) { |
|
1214 return true; |
|
1215 } |
|
1216 |
|
1217 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL; |
|
1218 if (aCanRaise) |
|
1219 flags |= nsIFocusManager::FLAG_RAISE; |
|
1220 |
|
1221 nsCOMPtr<nsIDOMElement> node = do_QueryInterface(mFrameElement); |
|
1222 fm->SetFocus(node, flags); |
|
1223 return true; |
|
1224 } |
|
1225 |
|
1226 nsIntPoint |
|
1227 TabParent::GetChildProcessOffset() |
|
1228 { |
|
1229 // The "toplevel widget" in child processes is always at position |
|
1230 // 0,0. Map the event coordinates to match that. |
|
1231 |
|
1232 nsIntPoint offset(0, 0); |
|
1233 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
1234 if (!frameLoader) { |
|
1235 return offset; |
|
1236 } |
|
1237 nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent(); |
|
1238 if (!targetFrame) { |
|
1239 return offset; |
|
1240 } |
|
1241 |
|
1242 // Find out how far we're offset from the nearest widget. |
|
1243 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1244 if (!widget) { |
|
1245 return offset; |
|
1246 } |
|
1247 nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, |
|
1248 nsIntPoint(0, 0), |
|
1249 targetFrame); |
|
1250 |
|
1251 return LayoutDeviceIntPoint::ToUntyped(LayoutDeviceIntPoint::FromAppUnitsToNearest( |
|
1252 pt, targetFrame->PresContext()->AppUnitsPerDevPixel())); |
|
1253 } |
|
1254 |
|
1255 bool |
|
1256 TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& event) |
|
1257 { |
|
1258 NS_ENSURE_TRUE(mFrameElement, true); |
|
1259 |
|
1260 WidgetKeyboardEvent localEvent(event); |
|
1261 // Set mNoCrossProcessBoundaryForwarding to avoid this event from |
|
1262 // being infinitely redispatched and forwarded to the child again. |
|
1263 localEvent.mFlags.mNoCrossProcessBoundaryForwarding = true; |
|
1264 |
|
1265 // Here we convert the WidgetEvent that we received to an nsIDOMEvent |
|
1266 // to be able to dispatch it to the <browser> element as the target element. |
|
1267 nsIDocument* doc = mFrameElement->OwnerDoc(); |
|
1268 nsIPresShell* presShell = doc->GetShell(); |
|
1269 NS_ENSURE_TRUE(presShell, true); |
|
1270 nsPresContext* presContext = presShell->GetPresContext(); |
|
1271 NS_ENSURE_TRUE(presContext, true); |
|
1272 |
|
1273 EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent); |
|
1274 return true; |
|
1275 } |
|
1276 |
|
1277 /** |
|
1278 * Try to answer query event using cached text. |
|
1279 * |
|
1280 * For NS_QUERY_SELECTED_TEXT, fail if the cache doesn't contain the whole |
|
1281 * selected range. (This shouldn't happen because PuppetWidget should have |
|
1282 * already sent the whole selection.) |
|
1283 * |
|
1284 * For NS_QUERY_TEXT_CONTENT, fail only if the cache doesn't overlap with |
|
1285 * the queried range. Note the difference from above. We use |
|
1286 * this behavior because a normal NS_QUERY_TEXT_CONTENT event is allowed to |
|
1287 * have out-of-bounds offsets, so that widget can request content without |
|
1288 * knowing the exact length of text. It's up to widget to handle cases when |
|
1289 * the returned offset/length are different from the queried offset/length. |
|
1290 * |
|
1291 * For NS_QUERY_TEXT_RECT, fail if cached offset/length aren't equals to input. |
|
1292 * Cocoa widget always queries selected offset, so it works on it. |
|
1293 * |
|
1294 * For NS_QUERY_CARET_RECT, fail if cached offset isn't equals to input |
|
1295 */ |
|
1296 bool |
|
1297 TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent) |
|
1298 { |
|
1299 aEvent.mSucceeded = false; |
|
1300 aEvent.mWasAsync = false; |
|
1301 aEvent.mReply.mFocusedWidget = nsCOMPtr<nsIWidget>(GetWidget()).get(); |
|
1302 |
|
1303 switch (aEvent.message) |
|
1304 { |
|
1305 case NS_QUERY_SELECTED_TEXT: |
|
1306 { |
|
1307 aEvent.mReply.mOffset = std::min(mIMESelectionAnchor, mIMESelectionFocus); |
|
1308 if (mIMESelectionAnchor == mIMESelectionFocus) { |
|
1309 aEvent.mReply.mString.Truncate(0); |
|
1310 } else { |
|
1311 if (mIMESelectionAnchor > mIMECacheText.Length() || |
|
1312 mIMESelectionFocus > mIMECacheText.Length()) { |
|
1313 break; |
|
1314 } |
|
1315 uint32_t selLen = mIMESelectionAnchor > mIMESelectionFocus ? |
|
1316 mIMESelectionAnchor - mIMESelectionFocus : |
|
1317 mIMESelectionFocus - mIMESelectionAnchor; |
|
1318 aEvent.mReply.mString = Substring(mIMECacheText, |
|
1319 aEvent.mReply.mOffset, |
|
1320 selLen); |
|
1321 } |
|
1322 aEvent.mReply.mReversed = mIMESelectionFocus < mIMESelectionAnchor; |
|
1323 aEvent.mReply.mHasSelection = true; |
|
1324 aEvent.mSucceeded = true; |
|
1325 } |
|
1326 break; |
|
1327 case NS_QUERY_TEXT_CONTENT: |
|
1328 { |
|
1329 uint32_t inputOffset = aEvent.mInput.mOffset, |
|
1330 inputEnd = inputOffset + aEvent.mInput.mLength; |
|
1331 |
|
1332 if (inputEnd > mIMECacheText.Length()) { |
|
1333 inputEnd = mIMECacheText.Length(); |
|
1334 } |
|
1335 if (inputEnd < inputOffset) { |
|
1336 break; |
|
1337 } |
|
1338 aEvent.mReply.mOffset = inputOffset; |
|
1339 aEvent.mReply.mString = Substring(mIMECacheText, |
|
1340 inputOffset, |
|
1341 inputEnd - inputOffset); |
|
1342 aEvent.mSucceeded = true; |
|
1343 } |
|
1344 break; |
|
1345 case NS_QUERY_TEXT_RECT: |
|
1346 { |
|
1347 if (aEvent.mInput.mOffset != mIMECompositionRectOffset || |
|
1348 aEvent.mInput.mLength != 1) { |
|
1349 break; |
|
1350 } |
|
1351 |
|
1352 aEvent.mReply.mOffset = mIMECompositionRectOffset; |
|
1353 aEvent.mReply.mRect = mIMECompositionRect - GetChildProcessOffset(); |
|
1354 aEvent.mSucceeded = true; |
|
1355 } |
|
1356 break; |
|
1357 case NS_QUERY_CARET_RECT: |
|
1358 { |
|
1359 if (aEvent.mInput.mOffset != mIMECompositionRectOffset) { |
|
1360 break; |
|
1361 } |
|
1362 |
|
1363 aEvent.mReply.mOffset = mIMECompositionRectOffset; |
|
1364 aEvent.mReply.mRect = mIMECaretRect - GetChildProcessOffset(); |
|
1365 aEvent.mSucceeded = true; |
|
1366 } |
|
1367 break; |
|
1368 } |
|
1369 return true; |
|
1370 } |
|
1371 |
|
1372 bool |
|
1373 TabParent::SendCompositionEvent(WidgetCompositionEvent& event) |
|
1374 { |
|
1375 if (mIsDestroyed) { |
|
1376 return false; |
|
1377 } |
|
1378 mIMEComposing = event.message != NS_COMPOSITION_END; |
|
1379 mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus); |
|
1380 if (mIMECompositionEnding) |
|
1381 return true; |
|
1382 event.mSeqno = ++mIMESeqno; |
|
1383 return PBrowserParent::SendCompositionEvent(event); |
|
1384 } |
|
1385 |
|
1386 /** |
|
1387 * During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION, |
|
1388 * widget usually sends a NS_TEXT_TEXT event to finalize or clear the |
|
1389 * composition, respectively |
|
1390 * |
|
1391 * Because the event will not reach content in time, we intercept it |
|
1392 * here and pass the text as the EndIMEComposition return value |
|
1393 */ |
|
1394 bool |
|
1395 TabParent::SendTextEvent(WidgetTextEvent& event) |
|
1396 { |
|
1397 if (mIsDestroyed) { |
|
1398 return false; |
|
1399 } |
|
1400 if (mIMECompositionEnding) { |
|
1401 mIMECompositionText = event.theText; |
|
1402 return true; |
|
1403 } |
|
1404 |
|
1405 // We must be able to simulate the selection because |
|
1406 // we might not receive selection updates in time |
|
1407 if (!mIMEComposing) { |
|
1408 mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus); |
|
1409 } |
|
1410 mIMESelectionAnchor = mIMESelectionFocus = |
|
1411 mIMECompositionStart + event.theText.Length(); |
|
1412 |
|
1413 event.mSeqno = ++mIMESeqno; |
|
1414 return PBrowserParent::SendTextEvent(event); |
|
1415 } |
|
1416 |
|
1417 bool |
|
1418 TabParent::SendSelectionEvent(WidgetSelectionEvent& event) |
|
1419 { |
|
1420 if (mIsDestroyed) { |
|
1421 return false; |
|
1422 } |
|
1423 mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0); |
|
1424 mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0); |
|
1425 event.mSeqno = ++mIMESeqno; |
|
1426 return PBrowserParent::SendSelectionEvent(event); |
|
1427 } |
|
1428 |
|
1429 /*static*/ TabParent* |
|
1430 TabParent::GetFrom(nsFrameLoader* aFrameLoader) |
|
1431 { |
|
1432 if (!aFrameLoader) { |
|
1433 return nullptr; |
|
1434 } |
|
1435 PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser(); |
|
1436 return static_cast<TabParent*>(remoteBrowser); |
|
1437 } |
|
1438 |
|
1439 /*static*/ TabParent* |
|
1440 TabParent::GetFrom(nsIContent* aContent) |
|
1441 { |
|
1442 nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aContent); |
|
1443 if (!loaderOwner) { |
|
1444 return nullptr; |
|
1445 } |
|
1446 nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader(); |
|
1447 return GetFrom(frameLoader); |
|
1448 } |
|
1449 |
|
1450 RenderFrameParent* |
|
1451 TabParent::GetRenderFrame() |
|
1452 { |
|
1453 if (ManagedPRenderFrameParent().IsEmpty()) { |
|
1454 return nullptr; |
|
1455 } |
|
1456 return static_cast<RenderFrameParent*>(ManagedPRenderFrameParent()[0]); |
|
1457 } |
|
1458 |
|
1459 bool |
|
1460 TabParent::RecvEndIMEComposition(const bool& aCancel, |
|
1461 nsString* aComposition) |
|
1462 { |
|
1463 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1464 if (!widget) |
|
1465 return true; |
|
1466 |
|
1467 mIMECompositionEnding = true; |
|
1468 |
|
1469 widget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION : |
|
1470 REQUEST_TO_COMMIT_COMPOSITION)); |
|
1471 |
|
1472 mIMECompositionEnding = false; |
|
1473 *aComposition = mIMECompositionText; |
|
1474 mIMECompositionText.Truncate(0); |
|
1475 return true; |
|
1476 } |
|
1477 |
|
1478 bool |
|
1479 TabParent::RecvGetInputContext(int32_t* aIMEEnabled, |
|
1480 int32_t* aIMEOpen, |
|
1481 intptr_t* aNativeIMEContext) |
|
1482 { |
|
1483 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1484 if (!widget) { |
|
1485 *aIMEEnabled = IMEState::DISABLED; |
|
1486 *aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED; |
|
1487 *aNativeIMEContext = 0; |
|
1488 return true; |
|
1489 } |
|
1490 |
|
1491 InputContext context = widget->GetInputContext(); |
|
1492 *aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled); |
|
1493 *aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen); |
|
1494 *aNativeIMEContext = reinterpret_cast<intptr_t>(context.mNativeIMEContext); |
|
1495 return true; |
|
1496 } |
|
1497 |
|
1498 bool |
|
1499 TabParent::RecvSetInputContext(const int32_t& aIMEEnabled, |
|
1500 const int32_t& aIMEOpen, |
|
1501 const nsString& aType, |
|
1502 const nsString& aInputmode, |
|
1503 const nsString& aActionHint, |
|
1504 const int32_t& aCause, |
|
1505 const int32_t& aFocusChange) |
|
1506 { |
|
1507 // mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus |
|
1508 // When the input mode is set to anything but IMEState::DISABLED, |
|
1509 // mIMETabParent should be set to this |
|
1510 mIMETabParent = |
|
1511 aIMEEnabled != static_cast<int32_t>(IMEState::DISABLED) ? this : nullptr; |
|
1512 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1513 if (!widget || !AllowContentIME()) |
|
1514 return true; |
|
1515 |
|
1516 InputContext context; |
|
1517 context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled); |
|
1518 context.mIMEState.mOpen = static_cast<IMEState::Open>(aIMEOpen); |
|
1519 context.mHTMLInputType.Assign(aType); |
|
1520 context.mHTMLInputInputmode.Assign(aInputmode); |
|
1521 context.mActionHint.Assign(aActionHint); |
|
1522 InputContextAction action( |
|
1523 static_cast<InputContextAction::Cause>(aCause), |
|
1524 static_cast<InputContextAction::FocusChange>(aFocusChange)); |
|
1525 widget->SetInputContext(context, action); |
|
1526 |
|
1527 nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); |
|
1528 if (!observerService) |
|
1529 return true; |
|
1530 |
|
1531 nsAutoString state; |
|
1532 state.AppendInt(aIMEEnabled); |
|
1533 observerService->NotifyObservers(nullptr, "ime-enabled-state-changed", state.get()); |
|
1534 |
|
1535 return true; |
|
1536 } |
|
1537 |
|
1538 bool |
|
1539 TabParent::RecvIsParentWindowMainWidgetVisible(bool* aIsVisible) |
|
1540 { |
|
1541 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement); |
|
1542 if (!frame) |
|
1543 return true; |
|
1544 nsCOMPtr<nsIDOMWindowUtils> windowUtils = |
|
1545 do_QueryInterface(frame->OwnerDoc()->GetWindow()); |
|
1546 nsresult rv = windowUtils->GetIsParentWindowMainWidgetVisible(aIsVisible); |
|
1547 return NS_SUCCEEDED(rv); |
|
1548 } |
|
1549 |
|
1550 bool |
|
1551 TabParent::RecvGetDPI(float* aValue) |
|
1552 { |
|
1553 TryCacheDPIAndScale(); |
|
1554 |
|
1555 NS_ABORT_IF_FALSE(mDPI > 0, |
|
1556 "Must not ask for DPI before OwnerElement is received!"); |
|
1557 *aValue = mDPI; |
|
1558 return true; |
|
1559 } |
|
1560 |
|
1561 bool |
|
1562 TabParent::RecvGetDefaultScale(double* aValue) |
|
1563 { |
|
1564 TryCacheDPIAndScale(); |
|
1565 |
|
1566 NS_ABORT_IF_FALSE(mDefaultScale.scale > 0, |
|
1567 "Must not ask for scale before OwnerElement is received!"); |
|
1568 *aValue = mDefaultScale.scale; |
|
1569 return true; |
|
1570 } |
|
1571 |
|
1572 bool |
|
1573 TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue) |
|
1574 { |
|
1575 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement); |
|
1576 if (content) { |
|
1577 nsIPresShell* shell = content->OwnerDoc()->GetShell(); |
|
1578 if (shell) { |
|
1579 nsViewManager* vm = shell->GetViewManager(); |
|
1580 nsCOMPtr<nsIWidget> widget; |
|
1581 vm->GetRootWidget(getter_AddRefs(widget)); |
|
1582 if (widget) { |
|
1583 *aValue = reinterpret_cast<WindowsHandle>( |
|
1584 widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW)); |
|
1585 return true; |
|
1586 } |
|
1587 } |
|
1588 } |
|
1589 return false; |
|
1590 } |
|
1591 |
|
1592 bool |
|
1593 TabParent::ReceiveMessage(const nsString& aMessage, |
|
1594 bool aSync, |
|
1595 const StructuredCloneData* aCloneData, |
|
1596 CpowHolder* aCpows, |
|
1597 nsIPrincipal* aPrincipal, |
|
1598 InfallibleTArray<nsString>* aJSONRetVal) |
|
1599 { |
|
1600 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
1601 if (frameLoader && frameLoader->GetFrameMessageManager()) { |
|
1602 nsRefPtr<nsFrameMessageManager> manager = |
|
1603 frameLoader->GetFrameMessageManager(); |
|
1604 |
|
1605 manager->ReceiveMessage(mFrameElement, |
|
1606 aMessage, |
|
1607 aSync, |
|
1608 aCloneData, |
|
1609 aCpows, |
|
1610 aPrincipal, |
|
1611 aJSONRetVal); |
|
1612 } |
|
1613 return true; |
|
1614 } |
|
1615 |
|
1616 PIndexedDBParent* |
|
1617 TabParent::AllocPIndexedDBParent( |
|
1618 const nsCString& aGroup, |
|
1619 const nsCString& aASCIIOrigin, bool* /* aAllowed */) |
|
1620 { |
|
1621 return new IndexedDBParent(this); |
|
1622 } |
|
1623 |
|
1624 bool |
|
1625 TabParent::DeallocPIndexedDBParent(PIndexedDBParent* aActor) |
|
1626 { |
|
1627 delete aActor; |
|
1628 return true; |
|
1629 } |
|
1630 |
|
1631 bool |
|
1632 TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor, |
|
1633 const nsCString& aGroup, |
|
1634 const nsCString& aASCIIOrigin, |
|
1635 bool* aAllowed) |
|
1636 { |
|
1637 nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate(); |
|
1638 NS_ENSURE_TRUE(mgr, false); |
|
1639 |
|
1640 if (!IndexedDatabaseManager::IsMainProcess()) { |
|
1641 NS_RUNTIMEABORT("Not supported yet!"); |
|
1642 } |
|
1643 |
|
1644 nsresult rv; |
|
1645 |
|
1646 // XXXbent Need to make sure we have a whitelist for chrome databases! |
|
1647 |
|
1648 // Verify that the child is requesting to access a database it's allowed to |
|
1649 // see. (aASCIIOrigin here specifies a TabContext + a website origin, and |
|
1650 // we're checking that the TabContext may access it.) |
|
1651 // |
|
1652 // We have to check IsBrowserOrApp() because TabContextMayAccessOrigin will |
|
1653 // fail if we're not a browser-or-app, since aASCIIOrigin will be a plain URI, |
|
1654 // but TabContextMayAccessOrigin will construct an extended origin using |
|
1655 // app-id 0. Note that as written below, we allow a non browser-or-app child |
|
1656 // to read any database. That's a security hole, but we don't ship a |
|
1657 // configuration which creates non browser-or-app children, so it's not a big |
|
1658 // deal. |
|
1659 if (!aASCIIOrigin.EqualsLiteral("chrome") && IsBrowserOrApp() && |
|
1660 !IndexedDatabaseManager::TabContextMayAccessOrigin(*this, aASCIIOrigin)) { |
|
1661 |
|
1662 NS_WARNING("App attempted to open databases that it does not have " |
|
1663 "permission to access!"); |
|
1664 return false; |
|
1665 } |
|
1666 |
|
1667 nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement()); |
|
1668 NS_ENSURE_TRUE(node, false); |
|
1669 |
|
1670 nsIDocument* doc = node->GetOwnerDocument(); |
|
1671 NS_ENSURE_TRUE(doc, false); |
|
1672 |
|
1673 nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow(); |
|
1674 NS_ENSURE_TRUE(window, false); |
|
1675 |
|
1676 // Let's do a current inner check to see if the inner is active or is in |
|
1677 // bf cache, and bail out if it's not active. |
|
1678 nsCOMPtr<nsPIDOMWindow> outer = doc->GetWindow(); |
|
1679 if (!outer || outer->GetCurrentInnerWindow() != window) { |
|
1680 *aAllowed = false; |
|
1681 return true; |
|
1682 } |
|
1683 |
|
1684 ContentParent* contentParent = Manager(); |
|
1685 NS_ASSERTION(contentParent, "Null manager?!"); |
|
1686 |
|
1687 nsRefPtr<IDBFactory> factory; |
|
1688 rv = IDBFactory::Create(window, aGroup, aASCIIOrigin, contentParent, |
|
1689 getter_AddRefs(factory)); |
|
1690 NS_ENSURE_SUCCESS(rv, false); |
|
1691 |
|
1692 if (!factory) { |
|
1693 *aAllowed = false; |
|
1694 return true; |
|
1695 } |
|
1696 |
|
1697 IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor); |
|
1698 actor->mFactory = factory; |
|
1699 actor->mASCIIOrigin = aASCIIOrigin; |
|
1700 |
|
1701 *aAllowed = true; |
|
1702 return true; |
|
1703 } |
|
1704 |
|
1705 // nsIAuthPromptProvider |
|
1706 |
|
1707 // This method is largely copied from nsDocShell::GetAuthPrompt |
|
1708 NS_IMETHODIMP |
|
1709 TabParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid, |
|
1710 void** aResult) |
|
1711 { |
|
1712 // we're either allowing auth, or it's a proxy request |
|
1713 nsresult rv; |
|
1714 nsCOMPtr<nsIPromptFactory> wwatch = |
|
1715 do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); |
|
1716 NS_ENSURE_SUCCESS(rv, rv); |
|
1717 |
|
1718 nsCOMPtr<nsIDOMWindow> window; |
|
1719 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement); |
|
1720 if (frame) |
|
1721 window = do_QueryInterface(frame->OwnerDoc()->GetWindow()); |
|
1722 |
|
1723 // Get an auth prompter for our window so that the parenting |
|
1724 // of the dialogs works as it should when using tabs. |
|
1725 return wwatch->GetPrompt(window, iid, |
|
1726 reinterpret_cast<void**>(aResult)); |
|
1727 } |
|
1728 |
|
1729 PColorPickerParent* |
|
1730 TabParent::AllocPColorPickerParent(const nsString& aTitle, |
|
1731 const nsString& aInitialColor) |
|
1732 { |
|
1733 return new ColorPickerParent(aTitle, aInitialColor); |
|
1734 } |
|
1735 |
|
1736 bool |
|
1737 TabParent::DeallocPColorPickerParent(PColorPickerParent* actor) |
|
1738 { |
|
1739 delete actor; |
|
1740 return true; |
|
1741 } |
|
1742 |
|
1743 bool |
|
1744 TabParent::RecvInitRenderFrame(PRenderFrameParent* aFrame, |
|
1745 ScrollingBehavior* aScrolling, |
|
1746 TextureFactoryIdentifier* aTextureFactoryIdentifier, |
|
1747 uint64_t* aLayersId, |
|
1748 bool *aSuccess) |
|
1749 { |
|
1750 *aScrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING; |
|
1751 *aTextureFactoryIdentifier = TextureFactoryIdentifier(); |
|
1752 *aLayersId = 0; |
|
1753 |
|
1754 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); |
|
1755 if (!frameLoader) { |
|
1756 NS_WARNING("Can't allocate graphics resources. May already be shutting down."); |
|
1757 *aSuccess = false; |
|
1758 return true; |
|
1759 } |
|
1760 |
|
1761 static_cast<RenderFrameParent*>(aFrame)->Init(frameLoader, *aScrolling, |
|
1762 aTextureFactoryIdentifier, aLayersId); |
|
1763 |
|
1764 *aSuccess = true; |
|
1765 return true; |
|
1766 } |
|
1767 |
|
1768 PRenderFrameParent* |
|
1769 TabParent::AllocPRenderFrameParent() |
|
1770 { |
|
1771 MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty()); |
|
1772 return new RenderFrameParent(); |
|
1773 } |
|
1774 |
|
1775 bool |
|
1776 TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame) |
|
1777 { |
|
1778 delete aFrame; |
|
1779 return true; |
|
1780 } |
|
1781 |
|
1782 mozilla::docshell::POfflineCacheUpdateParent* |
|
1783 TabParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI, |
|
1784 const URIParams& aDocumentURI, |
|
1785 const bool& aStickDocument) |
|
1786 { |
|
1787 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update = |
|
1788 new mozilla::docshell::OfflineCacheUpdateParent(OwnOrContainingAppId(), |
|
1789 IsBrowserElement()); |
|
1790 // Use this reference as the IPDL reference. |
|
1791 return update.forget().take(); |
|
1792 } |
|
1793 |
|
1794 bool |
|
1795 TabParent::RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor, |
|
1796 const URIParams& aManifestURI, |
|
1797 const URIParams& aDocumentURI, |
|
1798 const bool& aStickDocument) |
|
1799 { |
|
1800 MOZ_ASSERT(aActor); |
|
1801 |
|
1802 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update = |
|
1803 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor); |
|
1804 |
|
1805 nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aStickDocument); |
|
1806 if (NS_FAILED(rv) && !IsDestroyed()) { |
|
1807 // Inform the child of failure. |
|
1808 unused << update->SendFinish(false, false); |
|
1809 } |
|
1810 |
|
1811 return true; |
|
1812 } |
|
1813 |
|
1814 bool |
|
1815 TabParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor) |
|
1816 { |
|
1817 // Reclaim the IPDL reference. |
|
1818 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update = |
|
1819 dont_AddRef( |
|
1820 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor)); |
|
1821 return true; |
|
1822 } |
|
1823 |
|
1824 bool |
|
1825 TabParent::RecvSetOfflinePermission(const IPC::Principal& aPrincipal) |
|
1826 { |
|
1827 nsIPrincipal* principal = aPrincipal; |
|
1828 nsContentUtils::MaybeAllowOfflineAppByDefault(principal, nullptr); |
|
1829 return true; |
|
1830 } |
|
1831 |
|
1832 bool |
|
1833 TabParent::AllowContentIME() |
|
1834 { |
|
1835 nsFocusManager* fm = nsFocusManager::GetFocusManager(); |
|
1836 NS_ENSURE_TRUE(fm, false); |
|
1837 |
|
1838 nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent(); |
|
1839 if (focusedContent && focusedContent->IsEditable()) |
|
1840 return false; |
|
1841 |
|
1842 return true; |
|
1843 } |
|
1844 |
|
1845 already_AddRefed<nsFrameLoader> |
|
1846 TabParent::GetFrameLoader() const |
|
1847 { |
|
1848 nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(mFrameElement); |
|
1849 return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nullptr; |
|
1850 } |
|
1851 |
|
1852 void |
|
1853 TabParent::TryCacheDPIAndScale() |
|
1854 { |
|
1855 if (mDPI > 0) { |
|
1856 return; |
|
1857 } |
|
1858 |
|
1859 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
1860 |
|
1861 if (!widget && mFrameElement) { |
|
1862 // Even if we don't have a widget (e.g. because we're display:none), there's |
|
1863 // probably a widget somewhere in the hierarchy our frame element lives in. |
|
1864 widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc()); |
|
1865 } |
|
1866 |
|
1867 if (widget) { |
|
1868 mDPI = widget->GetDPI(); |
|
1869 mDefaultScale = widget->GetDefaultScale(); |
|
1870 } |
|
1871 } |
|
1872 |
|
1873 already_AddRefed<nsIWidget> |
|
1874 TabParent::GetWidget() const |
|
1875 { |
|
1876 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement); |
|
1877 if (!content) |
|
1878 return nullptr; |
|
1879 |
|
1880 nsIFrame *frame = content->GetPrimaryFrame(); |
|
1881 if (!frame) |
|
1882 return nullptr; |
|
1883 |
|
1884 nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(); |
|
1885 return widget.forget(); |
|
1886 } |
|
1887 |
|
1888 bool |
|
1889 TabParent::UseAsyncPanZoom() |
|
1890 { |
|
1891 bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop(); |
|
1892 bool asyncPanZoomEnabled = |
|
1893 Preferences::GetBool("layers.async-pan-zoom.enabled", false); |
|
1894 return (usingOffMainThreadCompositing && asyncPanZoomEnabled && |
|
1895 GetScrollingBehavior() == ASYNC_PAN_ZOOM); |
|
1896 } |
|
1897 |
|
1898 void |
|
1899 TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent, |
|
1900 ScrollableLayerGuid* aOutTargetGuid) |
|
1901 { |
|
1902 if (RenderFrameParent* rfp = GetRenderFrame()) { |
|
1903 rfp->NotifyInputEvent(aEvent, aOutTargetGuid); |
|
1904 } |
|
1905 } |
|
1906 |
|
1907 bool |
|
1908 TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, |
|
1909 const nsString& aURL, |
|
1910 const nsString& aName, |
|
1911 const nsString& aFeatures, |
|
1912 bool* aOutWindowOpened) |
|
1913 { |
|
1914 BrowserElementParent::OpenWindowResult opened = |
|
1915 BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener), |
|
1916 this, aURL, aName, aFeatures); |
|
1917 *aOutWindowOpened = (opened != BrowserElementParent::OPEN_WINDOW_CANCELLED); |
|
1918 return true; |
|
1919 } |
|
1920 |
|
1921 bool |
|
1922 TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* actor) |
|
1923 { |
|
1924 return true; |
|
1925 } |
|
1926 |
|
1927 bool |
|
1928 TabParent::RecvZoomToRect(const uint32_t& aPresShellId, |
|
1929 const ViewID& aViewId, |
|
1930 const CSSRect& aRect) |
|
1931 { |
|
1932 if (RenderFrameParent* rfp = GetRenderFrame()) { |
|
1933 rfp->ZoomToRect(aPresShellId, aViewId, aRect); |
|
1934 } |
|
1935 return true; |
|
1936 } |
|
1937 |
|
1938 bool |
|
1939 TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId, |
|
1940 const ViewID& aViewId, |
|
1941 const bool& aIsRoot, |
|
1942 const ZoomConstraints& aConstraints) |
|
1943 { |
|
1944 if (RenderFrameParent* rfp = GetRenderFrame()) { |
|
1945 rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aConstraints); |
|
1946 } |
|
1947 return true; |
|
1948 } |
|
1949 |
|
1950 bool |
|
1951 TabParent::RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid, |
|
1952 const bool& aPreventDefault) |
|
1953 { |
|
1954 if (RenderFrameParent* rfp = GetRenderFrame()) { |
|
1955 rfp->ContentReceivedTouch(aGuid, aPreventDefault); |
|
1956 } |
|
1957 return true; |
|
1958 } |
|
1959 |
|
1960 already_AddRefed<nsILoadContext> |
|
1961 TabParent::GetLoadContext() |
|
1962 { |
|
1963 nsCOMPtr<nsILoadContext> loadContext; |
|
1964 if (mLoadContext) { |
|
1965 loadContext = mLoadContext; |
|
1966 } else { |
|
1967 loadContext = new LoadContext(GetOwnerElement(), |
|
1968 OwnOrContainingAppId(), |
|
1969 true /* aIsContent */, |
|
1970 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW, |
|
1971 mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW, |
|
1972 IsBrowserElement()); |
|
1973 mLoadContext = loadContext; |
|
1974 } |
|
1975 return loadContext.forget(); |
|
1976 } |
|
1977 |
|
1978 /* Be careful if you call this method while proceding a real touch event. For |
|
1979 * example sending a touchstart during a real touchend may results into |
|
1980 * a busted mEventCaptureDepth and following touch events may not do what you |
|
1981 * expect. |
|
1982 */ |
|
1983 NS_IMETHODIMP |
|
1984 TabParent::InjectTouchEvent(const nsAString& aType, |
|
1985 uint32_t* aIdentifiers, |
|
1986 int32_t* aXs, |
|
1987 int32_t* aYs, |
|
1988 uint32_t* aRxs, |
|
1989 uint32_t* aRys, |
|
1990 float* aRotationAngles, |
|
1991 float* aForces, |
|
1992 uint32_t aCount, |
|
1993 int32_t aModifiers) |
|
1994 { |
|
1995 uint32_t msg; |
|
1996 nsContentUtils::GetEventIdAndAtom(aType, NS_TOUCH_EVENT, &msg); |
|
1997 if (msg != NS_TOUCH_START && msg != NS_TOUCH_MOVE && |
|
1998 msg != NS_TOUCH_END && msg != NS_TOUCH_CANCEL) { |
|
1999 return NS_ERROR_FAILURE; |
|
2000 } |
|
2001 |
|
2002 nsCOMPtr<nsIWidget> widget = GetWidget(); |
|
2003 if (!widget) { |
|
2004 return NS_ERROR_FAILURE; |
|
2005 } |
|
2006 |
|
2007 WidgetTouchEvent event(true, msg, widget); |
|
2008 event.modifiers = aModifiers; |
|
2009 event.time = PR_IntervalNow(); |
|
2010 |
|
2011 event.touches.SetCapacity(aCount); |
|
2012 for (uint32_t i = 0; i < aCount; ++i) { |
|
2013 nsRefPtr<Touch> t = new Touch(aIdentifiers[i], |
|
2014 nsIntPoint(aXs[i], aYs[i]), |
|
2015 nsIntPoint(aRxs[i], aRys[i]), |
|
2016 aRotationAngles[i], |
|
2017 aForces[i]); |
|
2018 |
|
2019 // Consider all injected touch events as changedTouches. For more details |
|
2020 // about the meaning of changedTouches for each event, see |
|
2021 // https://developer.mozilla.org/docs/Web/API/TouchEvent.changedTouches |
|
2022 t->mChanged = true; |
|
2023 event.touches.AppendElement(t); |
|
2024 } |
|
2025 |
|
2026 if ((msg == NS_TOUCH_END || msg == NS_TOUCH_CANCEL) && sEventCapturer) { |
|
2027 WidgetGUIEvent* guiEvent = event.AsGUIEvent(); |
|
2028 TryCapture(*guiEvent); |
|
2029 } |
|
2030 |
|
2031 SendRealTouchEvent(event); |
|
2032 return NS_OK; |
|
2033 } |
|
2034 |
|
2035 NS_IMETHODIMP |
|
2036 TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom) |
|
2037 { |
|
2038 *useAsyncPanZoom = UseAsyncPanZoom(); |
|
2039 return NS_OK; |
|
2040 } |
|
2041 |
|
2042 NS_IMETHODIMP |
|
2043 TabParent::SetIsDocShellActive(bool isActive) |
|
2044 { |
|
2045 unused << SendSetIsDocShellActive(isActive); |
|
2046 return NS_OK; |
|
2047 } |
|
2048 |
|
2049 } // namespace tabs |
|
2050 } // namespace mozilla |