// This method sets the request's referrerURL, as specified by the "determine // request's referrer" steps from Referrer Policy [1]. // The actual referrer policy and stripping is dealt with by HttpBaseChannel, // this always sets the full API referrer URL of the relevant global if it is // not already a url or no-referrer. // [1]: https://w3c.github.io/webappsec/specs/referrer-policy/#determine-requests-referrer nsresult UpdateRequestReferrer(nsIGlobalObject* aGlobal, InternalRequest* aRequest) { nsAutoString originalReferrer; aRequest->GetReferrer(originalReferrer); // If it is no-referrer ("") or a URL, don't modify. if (!originalReferrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) { return NS_OK; } nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal); if (window) { nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); if (doc) { nsAutoString referrer; doc->GetReferrer(referrer); aRequest->SetReferrer(referrer); } } else { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); WorkerPrivate::LocationInfo& info = worker->GetLocationInfo(); aRequest->SetReferrer(NS_ConvertUTF8toUTF16(info.mHref)); } return NS_OK; }
already_AddRefed<URL> ParseURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput, ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref); RefPtr<URL> url = URL::WorkerConstructor(aGlobal, aInput, baseURL, aRv); if (NS_WARN_IF(aRv.Failed())) { aRv.ThrowTypeError<MSG_INVALID_URL>(aInput); } return url.forget(); }
NS_IMETHOD Run() override { AssertIsOnMainThread(); MutexAutoLock lock(mPromiseProxy->Lock()); if (mPromiseProxy->CleanedUp()) { return NS_OK; } nsCOMPtr<nsPIDOMWindowOuter> window; nsresult rv = OpenWindow(getter_AddRefs(window)); if (NS_SUCCEEDED(rv)) { MOZ_ASSERT(window); WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate(); MOZ_ASSERT(workerPrivate); WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo(); nsCOMPtr<nsIURI> baseURI; nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIDocShell> docShell = window->GetDocShell(); nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell); if (!webProgress) { return NS_ERROR_FAILURE; } RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); MOZ_ASSERT(swm); nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal(); MOZ_ASSERT(principal); RefPtr<ServiceWorkerRegistrationInfo> registration = swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope)); if (NS_WARN_IF(!registration)) { return NS_ERROR_FAILURE; } RefPtr<ServiceWorkerInfo> serviceWorkerInfo = registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID()); if (NS_WARN_IF(!serviceWorkerInfo)) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIWebProgressListener> listener = new WebProgressListener(mPromiseProxy, serviceWorkerInfo->WorkerPrivate(), window, baseURI); rv = webProgress->AddProgressListener(listener, nsIWebProgress::NOTIFY_STATE_DOCUMENT); MOZ_ASSERT(NS_SUCCEEDED(rv)); return NS_OK; } RefPtr<ResolveOpenWindowRunnable> resolveRunnable = new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv); NS_WARN_IF(!resolveRunnable->Dispatch()); return NS_OK; }
nsresult OpenWindow(nsPIDOMWindowOuter** aWindow) { WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate(); // [[1. Let url be the result of parsing url with entry settings object's API // base URL.]] nsCOMPtr<nsIURI> uri; WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo(); nsCOMPtr<nsIURI> baseURI; nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_TYPE_ERR; } rv = NS_NewURI(getter_AddRefs(uri), mUrl, nullptr, baseURI); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_TYPE_ERR; } // [[6.1 Open Window]] nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (XRE_IsContentProcess()) { // ContentProcess nsCOMPtr<nsIWindowWatcher> wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch)); NS_ENSURE_STATE(pwwatch); nsCString spec; uri->GetSpec(spec); nsCOMPtr<mozIDOMWindowProxy> newWindow; pwwatch->OpenWindow2(nullptr, spec.get(), nullptr, nullptr, false, false, true, nullptr, nullptr, getter_AddRefs(newWindow)); nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow); pwindow.forget(aWindow); return NS_OK; } // Find the most recent browser window and open a new tab in it. nsCOMPtr<nsPIDOMWindowOuter> browserWindow = nsContentUtils::GetMostRecentNonPBWindow(); if (!browserWindow) { // It is possible to be running without a browser window on Mac OS, so // we need to open a new chrome window. // TODO(catalinb): open new chrome window. Bug 1218080 return NS_ERROR_FAILURE; } nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(browserWindow); if (NS_WARN_IF(!chromeWin)) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIBrowserDOMWindow> bwin; chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin)); if (NS_WARN_IF(!bwin)) { return NS_ERROR_FAILURE; } nsCOMPtr<mozIDOMWindowProxy> win; rv = bwin->OpenURI(uri, nullptr, nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW, nsIBrowserDOMWindow::OPEN_NEW, getter_AddRefs(win)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } NS_ENSURE_STATE(win); nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win); pWin.forget(aWindow); return NS_OK; }
NS_IMETHOD Run() override { AssertIsOnMainThread(); MutexAutoLock lock(mPromiseProxy->Lock()); if (mPromiseProxy->CleanedUp()) { return NS_OK; } #ifdef MOZ_WIDGET_ANDROID // This fires an intent that will start launching Fennec and foreground it, // if necessary. java::GeckoAppShell::OpenWindowForNotification(); #endif nsCOMPtr<nsPIDOMWindowOuter> window; nsresult rv = OpenWindow(getter_AddRefs(window)); if (NS_SUCCEEDED(rv)) { MOZ_ASSERT(window); rv = nsContentUtils::DispatchFocusChromeEvent(window); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate(); MOZ_ASSERT(workerPrivate); WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo(); nsCOMPtr<nsIURI> baseURI; nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIDocShell> docShell = window->GetDocShell(); nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell); if (!webProgress) { return NS_ERROR_FAILURE; } RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); MOZ_ASSERT(swm); nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal(); MOZ_ASSERT(principal); RefPtr<ServiceWorkerRegistrationInfo> registration = swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope)); if (NS_WARN_IF(!registration)) { return NS_ERROR_FAILURE; } RefPtr<ServiceWorkerInfo> serviceWorkerInfo = registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID()); if (NS_WARN_IF(!serviceWorkerInfo)) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIWebProgressListener> listener = new WebProgressListener(mPromiseProxy, serviceWorkerInfo->WorkerPrivate(), window, baseURI); rv = webProgress->AddProgressListener(listener, nsIWebProgress::NOTIFY_STATE_DOCUMENT); MOZ_ASSERT(NS_SUCCEEDED(rv)); return NS_OK; } #ifdef MOZ_WIDGET_ANDROID else if (rv == NS_ERROR_NOT_AVAILABLE) { // We couldn't get a browser window, so Fennec must not be running. // Send an Intent to launch Fennec and wait for "BrowserChrome:Ready" // to try opening a window again. nsCOMPtr<nsIObserverService> os = services::GetObserverService(); NS_ENSURE_STATE(os); WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate(); MOZ_ASSERT(workerPrivate); RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); MOZ_ASSERT(swm); nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal(); MOZ_ASSERT(principal); RefPtr<ServiceWorkerRegistrationInfo> registration = swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope)); if (NS_WARN_IF(!registration)) { return NS_ERROR_FAILURE; } RefPtr<ServiceWorkerInfo> serviceWorkerInfo = registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID()); if (NS_WARN_IF(!serviceWorkerInfo)) { return NS_ERROR_FAILURE; } os->AddObserver(static_cast<nsIObserver*>(serviceWorkerInfo->WorkerPrivate()), "BrowserChrome:Ready", true); serviceWorkerInfo->WorkerPrivate()->AddPendingWindow(this); return NS_OK; } #endif RefPtr<ResolveOpenWindowRunnable> resolveRunnable = new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv); Unused << NS_WARN_IF(!resolveRunnable->Dispatch()); return NS_OK; }