void HTMLAnchorElement::parseAttribute(Attribute* attr) { if (attr->name() == hrefAttr) { bool wasLink = isLink(); setIsLink(!attr->isNull()); if (wasLink != isLink()) setNeedsStyleRecalc(); if (isLink()) { String parsedURL = stripLeadingAndTrailingHTMLSpaces(attr->value()); if (document()->isDNSPrefetchEnabled()) { if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "https") || parsedURL.startsWith("//")) prefetchDNS(document()->completeURL(parsedURL).host()); } if (document()->page() && !document()->page()->javaScriptURLsAreAllowed() && protocolIsJavaScript(parsedURL)) { clearIsLink(); // FIXME: This is horribly factored. if (Attribute* hrefAttribute = getAttributeItem(hrefAttr)) hrefAttribute->setValue(nullAtom); } #ifdef ARTEMIS else if(protocolIsJavaScript(parsedURL) && !hasEventListeners(eventNames().clickEvent)) { // Don't set the onclick event handler if it already has one. setAttributeEventListener(eventNames().clickEvent, createAttributeEventListener(this, attr)); } #endif } invalidateCachedVisitedLinkHash(); } else if (attr->name() == nameAttr || attr->name() == titleAttr) { // Do nothing. } else if (attr->name() == relAttr) setRel(attr->value()); else HTMLElement::parseAttribute(attr); }
// We don't use m_url, as it may not be the final URL that the object loads, // depending on <param> values. bool HTMLPlugInImageElement::allowedToLoadFrameURL(const String& url) { ASSERT(document()); ASSERT(document()->frame()); if (document()->frame()->page()->frameCount() >= Page::maxNumberOfFrames) return false; KURL completeURL = document()->completeURL(url); if (contentFrame() && protocolIsJavaScript(completeURL) && !document()->securityOrigin()->canAccess(contentDocument()->securityOrigin())) return false; // We allow one level of self-reference because some sites depend on that. // But we don't allow more than one. bool foundSelfReference = false; for (Frame* frame = document()->frame(); frame; frame = frame->tree()->parent()) { if (equalIgnoringFragmentIdentifier(frame->document()->url(), completeURL)) { if (foundSelfReference) return false; foundSelfReference = true; } } return true; }
void MarkupAccumulator::appendQuotedURLAttributeValue(StringBuilder& result, const Element* element, const Attribute& attribute) { ASSERT(element->isURLAttribute(const_cast<Attribute*>(&attribute))); const String resolvedURLString = resolveURLIfNeeded(element, attribute.value()); UChar quoteChar = '\"'; String strippedURLString = resolvedURLString.stripWhiteSpace(); if (protocolIsJavaScript(strippedURLString)) { // minimal escaping for javascript urls if (strippedURLString.contains('"')) { if (strippedURLString.contains('\'')) strippedURLString.replace('\"', """); else quoteChar = '\''; } result.append(quoteChar); result.append(strippedURLString); result.append(quoteChar); return; } // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML. result.append(quoteChar); appendAttributeValue(result, resolvedURLString, false); result.append(quoteChar); }
void JSDOMWindow::setLocation(ExecState* exec, JSValue value) { Frame* lexicalFrame = toLexicalFrame(exec); if (!lexicalFrame) return; #if ENABLE(DASHBOARD_SUPPORT) // To avoid breaking old widgets, make "var location =" in a top-level frame create // a property named "location" instead of performing a navigation (<rdar://problem/5688039>). if (Settings* settings = lexicalFrame->settings()) { if (settings->usesDashboardBackwardCompatibilityMode() && !lexicalFrame->tree()->parent()) { if (allowsAccessFrom(exec)) putDirect(Identifier(exec, "location"), value); return; } } #endif Frame* frame = impl()->frame(); ASSERT(frame); KURL url = completeURL(exec, ustringToString(value.toString(exec))); if (url.isNull()) return; if (!shouldAllowNavigation(exec, frame)) return; if (!protocolIsJavaScript(url) || allowsAccessFrom(exec)) { // We want a new history item if this JS was called via a user gesture frame->redirectScheduler()->scheduleLocationChange(url, lexicalFrame->loader()->outgoingReferrer(), !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, processingUserGesture()); } }
void Location::reload(DOMWindow* callingWindow) { if (!m_frame) return; if (protocolIsJavaScript(m_frame->document()->url())) return; m_frame->navigationScheduler().scheduleRefresh(); }
void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool lockBackForwardList) { Frame* callingOrEntered = callingOrEnteredFrame(); if (!callingOrEntered) return; if (!protocolIsJavaScript(url) || ScriptController::isSafeScript(frame)) frame->redirectScheduler()->scheduleLocationChange(url.string(), callingOrEntered->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); }
inline bool NavigationScheduler::shouldScheduleNavigation(const URL& url) const { if (!shouldScheduleNavigation()) return false; if (protocolIsJavaScript(url)) return true; return NavigationDisablerForBeforeUnload::isNavigationAllowed(); }
// We don't use m_url, as it may not be the final URL that the object loads, // depending on <param> values. bool HTMLPlugInElement::allowedToLoadFrameURL(const String& url) { KURL completeURL = document().completeURL(url); if (contentFrame() && protocolIsJavaScript(completeURL) && !document().securityOrigin()->canAccess(contentDocument()->securityOrigin())) return false; return document().frame()->isURLAllowed(completeURL); }
static void navigateIfAllowed(ExecState* exec, Frame* frame, const KURL& url, bool lockHistory, bool lockBackForwardList) { Frame* lexicalFrame = toLexicalFrame(exec); if (!lexicalFrame) return; if (!protocolIsJavaScript(url) || allowsAccessFromFrame(exec, frame)) frame->redirectScheduler()->scheduleLocationChange(url.string(), lexicalFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture(exec)); }
static bool semicolonSeparatedValueContainsJavaScriptURL(const String& value) { Vector<String> valueList; value.split(';', valueList); for (size_t i = 0; i < valueList.size(); ++i) { if (protocolIsJavaScript(valueList[i])) return true; } return false; }
JSValue JSLocation::reload(ExecState* exec, const ArgList&) { Frame* frame = impl()->frame(); if (!frame || !allowsAccessFromFrame(exec, frame)) return jsUndefined(); if (!protocolIsJavaScript(frame->loader()->url())) frame->redirectScheduler()->scheduleRefresh(processingUserGesture(exec)); return jsUndefined(); }
static String semicolonSeparatedValueContainingJavaScriptURL(const String& value) { Vector<String> valueList; value.split(';', valueList); for (size_t i = 0; i < valueList.size(); ++i) { String stripped = stripLeadingAndTrailingHTMLSpaces(valueList[i]); if (protocolIsJavaScript(stripped)) return stripped; } return emptyString(); }
bool ScriptController::executeIfJavaScriptURL(const KURL& url, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL) { if (!protocolIsJavaScript(url)) return false; if (!m_frame->page() || !m_frame->page()->javaScriptURLsAreAllowed() || !m_frame->document()->contentSecurityPolicy()->allowJavaScriptURLs() || m_frame->inViewSourceMode()) return true; // We need to hold onto the Frame here because executing script can // destroy the frame. RefPtr<Frame> protector(m_frame); RefPtr<Document> ownerDocument(m_frame->document()); const int javascriptSchemeLength = sizeof("javascript:") - 1; String decodedURL = decodeURLEscapeSequences(url.string()); ScriptValue result = executeScript(decodedURL.substring(javascriptSchemeLength)); // If executing script caused this frame to be removed from the page, we // don't want to try to replace its document! if (!m_frame->page()) return true; String scriptResult; #if USE(JSC) JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld()); JSC::ExecState* exec = shell->window()->globalExec(); if (!result.getString(exec, scriptResult)) return true; #else if (!result.getString(scriptResult)) return true; #endif // FIXME: We should always replace the document, but doing so // synchronously can cause crashes: // http://bugs.webkit.org/show_bug.cgi?id=16782 if (shouldReplaceDocumentIfJavaScriptURL == ReplaceDocumentIfJavaScriptURL) { // We're still in a frame, so there should be a DocumentLoader. ASSERT(m_frame->document()->loader()); // DocumentWriter::replaceDocument can cause the DocumentLoader to get deref'ed and possible destroyed, // so protect it with a RefPtr. if (RefPtr<DocumentLoader> loader = m_frame->document()->loader()) loader->writer()->replaceDocument(scriptResult, ownerDocument.get()); } return true; }
// Helper for window.open() and window.showModalDialog() static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicFrame, Frame* openerFrame, const String& url, const String& frameName, const WindowFeatures& windowFeatures, JSValue dialogArgs) { ASSERT(lexicalFrame); ASSERT(dynamicFrame); ResourceRequest request; // For whatever reason, Firefox uses the dynamicGlobalObject to determine // the outgoingReferrer. We replicate that behavior here. String referrer = dynamicFrame->loader()->outgoingReferrer(); request.setHTTPReferrer(referrer); FrameLoader::addHTTPOriginIfNeeded(request, dynamicFrame->loader()->outgoingOrigin()); FrameLoadRequest frameRequest(request, frameName); // FIXME: It's much better for client API if a new window starts with a URL, here where we // know what URL we are going to open. Unfortunately, this code passes the empty string // for the URL, but there's a reason for that. Before loading we have to set up the opener, // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently // do an allowsAccessFrom call using the window we create, which can't be done before creating it. // We'd have to resolve all those issues to pass the URL instead of "". bool created; // We pass the opener frame for the lookupFrame in case the active frame is different from // the opener frame, and the name references a frame relative to the opener frame. Frame* newFrame = createWindow(lexicalFrame, openerFrame, frameRequest, windowFeatures, created); if (!newFrame) return 0; newFrame->loader()->setOpener(openerFrame); newFrame->page()->setOpenedByDOM(); // FIXME: If a window is created from an isolated world, what are the consequences of this? 'dialogArguments' only appears back in the normal world? JSDOMWindow* newWindow = toJSDOMWindow(newFrame, normalWorld(exec->globalData())); if (dialogArgs) newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs); if (!protocolIsJavaScript(url) || newWindow->allowsAccessFrom(exec)) { KURL completedURL = url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(exec, url); bool userGesture = processingUserGesture(); if (created) newFrame->loader()->changeLocation(completedURL, referrer, false, false, userGesture); else if (!url.isEmpty()) newFrame->redirectScheduler()->scheduleLocationChange(completedURL.string(), referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture); } return newFrame; }
void MixedContentChecker::checkFormForMixedContent(SecurityOrigin* securityOrigin, const URL& url) const { // Unconditionally allow javascript: URLs as form actions as some pages do this and it does not introduce // a mixed content issue. if (protocolIsJavaScript(url)) return; if (!isMixedContent(securityOrigin, url)) return; String message = makeString("The page at ", m_frame.document()->url().stringCenterEllipsizedToLength(), " contains a form which targets an insecure URL ", url.stringCenterEllipsizedToLength(), ".\n"); m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Warning, message); client().didDisplayInsecureContent(); }
void Location::reload(DOMWindow* activeWindow) { if (!m_frame) return; // FIXME: It's not clear this cross-origin security check is valuable. // We allow one page to change the location of another. Why block attempts to reload? // Other location operations simply block use of JavaScript URLs cross origin. DOMWindow* targetWindow = m_frame->document()->domWindow(); if (!activeWindow->securityOrigin()->canAccess(targetWindow->securityOrigin())) { targetWindow->printErrorMessage(targetWindow->crossDomainAccessErrorMessage(activeWindow)); return; } if (protocolIsJavaScript(m_frame->document()->url())) return; m_frame->navigationScheduler()->scheduleRefresh(); }
v8::Handle<v8::Value> V8Location::reloadCallback(const v8::Arguments& args) { // FIXME: we ignore the "forceget" parameter. INC_STATS("DOM.Location.reload"); v8::Handle<v8::Object> holder = args.Holder(); Location* imp = V8Location::toNative(holder); Frame* frame = imp->frame(); if (!frame || !ScriptController::isSafeScript(frame)) return v8::Undefined(); if (!protocolIsJavaScript(frame->loader()->url())) frame->redirectScheduler()->scheduleRefresh(processingUserGesture()); return v8::Undefined(); }
bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument) { if (!protocolIsJavaScript(url)) return false; if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed()) return true; if (m_frame->inViewSourceMode()) return true; #if PLATFORM(APOLLO) // We should return true even though the script is not going to be executed. // Otherwise the frame will actually try to navigate to "javascript:" // which will eventually fail, but will also stop any other in progress requests in this page // like CSS files, images or JS files if (!m_frame->loader()->client()->canExecuteScriptURL()) return true; #endif const int javascriptSchemeLength = sizeof("javascript:") - 1; String decodedURL = decodeURLEscapeSequences(url.string()); ScriptValue result; if (xssAuditor()->canEvaluateJavaScriptURL(decodedURL)) result = executeScript(decodedURL.substring(javascriptSchemeLength), userGesture, AllowXSS); String scriptResult; #if USE(JSC) JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld()); JSC::ExecState* exec = shell->window()->globalExec(); if (!result.getString(exec, scriptResult)) return true; #else if (!result.getString(scriptResult)) return true; #endif // FIXME: We should always replace the document, but doing so // synchronously can cause crashes: // http://bugs.webkit.org/show_bug.cgi?id=16782 if (replaceDocument) m_frame->loader()->writer()->replaceDocument(scriptResult); return true; }
void PluginView::performJavaScriptURLRequest(URLRequest* request) { ASSERT(protocolIsJavaScript(request->request().url())); RefPtr<Frame> frame = m_pluginElement->document()->frame(); if (!frame) return; String jsString = decodeURLEscapeSequences(request->request().url().string().substring(sizeof("javascript:") - 1)); if (!request->target().isNull()) { // For security reasons, only allow JS requests to be made on the frame that contains the plug-in. if (frame->tree()->find(request->target()) != frame) { // Let the plug-in know that its frame load failed. m_plugin->frameDidFail(request->requestID(), false); return; } } // Evaluate the JavaScript code. Note that running JavaScript here could cause the plug-in to be destroyed, so we // grab references to the plug-in here. RefPtr<Plugin> plugin = m_plugin; ScriptValue result = m_pluginElement->document()->frame()->script()->executeScript(jsString); // Check if evaluating the JavaScript destroyed the plug-in. if (!plugin->controller()) return; ScriptState* scriptState = m_pluginElement->document()->frame()->script()->globalObject(pluginWorld())->globalExec(); String resultString; result.getString(scriptState, resultString); if (!request->target().isNull()) { // Just send back whether the frame load succeeded or not. if (resultString.isNull()) m_plugin->frameDidFail(request->requestID(), false); else m_plugin->frameDidFinishLoading(request->requestID()); return; } // Send the result back to the plug-in. plugin->didEvaluateJavaScript(request->requestID(), decodeURLEscapeSequences(request->request().url()), resultString); }
void PluginView::performURLRequest(URLRequest* request) { // First, check if this is a javascript: url. if (protocolIsJavaScript(request->request().url())) { performJavaScriptURLRequest(request); return; } if (!request->target().isNull()) { performFrameLoadURLRequest(request); return; } // This request is to load a URL and create a stream. RefPtr<Stream> stream = PluginView::Stream::create(this, request->requestID(), request->request()); addStream(stream.get()); stream->start(); }
void PluginView::performJavaScriptURLRequest(URLRequest* request) { ASSERT(protocolIsJavaScript(request->request().url())); RefPtr<Frame> frame = m_pluginElement->document()->frame(); if (!frame) return; String jsString = decodeURLEscapeSequences(request->request().url().string().substring(sizeof("javascript:") - 1)); if (!request->target().isNull()) { // For security reasons, only allow JS requests to be made on the frame that contains the plug-in. if (frame->tree()->find(request->target()) != frame) { // Let the plug-in know that its frame load failed. m_plugin->frameDidFail(request->requestID(), false); return; } } // Evaluate the JavaScript code. Note that running JavaScript here could cause the plug-in to be destroyed, so we // grab references to the plug-in here. RefPtr<Plugin> plugin = m_plugin; ScriptValue result = frame->script()->executeScript(jsString, request->allowPopups()); // Check if evaluating the JavaScript destroyed the plug-in. if (!plugin->controller()) return; // Don't notify the plug-in at all about targeted javascript: requests. This matches Mozilla and WebKit1. if (!request->target().isNull()) return; #if USE(JSC) ScriptState* scriptState = frame->script()->globalObject(pluginWorld())->globalExec(); #elif USE(V8) ScriptState* scriptState = ScriptState::forContext(frame->script()->proxy()->context(frame.get())); #endif String resultString; result.getString(scriptState, resultString); // Send the result back to the plug-in. plugin->didEvaluateJavaScript(request->requestID(), resultString); }
bool SVGAnimateElement::isSVGAnimationAttributeSettingJavaScriptURL(const Attribute& attribute) const { if ((attribute.name() == SVGNames::fromAttr || attribute.name() == SVGNames::toAttr) && attributeValueIsJavaScriptURL(attribute)) return true; if (attribute.name() == SVGNames::valuesAttr) { Vector<String> parts; if (!parseValues(attribute.value(), parts)) { // Assume the worst. return true; } for (const auto& part : parts) { if (protocolIsJavaScript(part)) return true; } } return SVGSMILElement::isSVGAnimationAttributeSettingJavaScriptURL(attribute); }
bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument) { if (!protocolIsJavaScript(url)) return false; if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed()) return true; if (m_frame->inViewSourceMode()) return true; const int javascriptSchemeLength = sizeof("javascript:") - 1; String script = decodeURLEscapeSequences(url.string().substring(javascriptSchemeLength)); ScriptValue result; if (xssAuditor()->canEvaluateJavaScriptURL(script)) result = executeScript(script, userGesture); String scriptResult; #if USE(JSC) JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld()); JSC::ExecState* exec = shell->window()->globalExec(); if (!result.getString(exec, scriptResult)) return true; #else if (!result.getString(scriptResult)) return true; #endif // FIXME: We should always replace the document, but doing so // synchronously can cause crashes: // http://bugs.webkit.org/show_bug.cgi?id=16782 if (replaceDocument) m_frame->loader()->replaceDocument(scriptResult); return true; }
void HTMLAnchorElement::parseAttribute(Attribute* attr) { if (attr->name() == hrefAttr) { bool wasLink = isLink(); setIsLink(!attr->isNull()); if (wasLink != isLink()) setNeedsStyleRecalc(); if (isLink()) { String parsedURL = stripLeadingAndTrailingHTMLSpaces(attr->value()); if (document()->isDNSPrefetchEnabled()) { if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "https") || parsedURL.startsWith("//")) prefetchDNS(document()->completeURL(parsedURL).host()); } if (document()->page() && !document()->page()->javaScriptURLsAreAllowed() && protocolIsJavaScript(parsedURL)) { clearIsLink(); attr->setValue(nullAtom); } } invalidateCachedVisitedLinkHash(); } else if (attr->name() == nameAttr || attr->name() == titleAttr) { // Do nothing. } else if (attr->name() == relAttr) setRel(attr->value()); else HTMLElement::parseAttribute(attr); }
JSValue JSDOMWindow::open(ExecState* exec) { String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : ustringToAtomicString(exec->argument(1).toString(exec)); WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2))); Frame* frame = impl()->frame(); if (!frame) return jsUndefined(); Frame* lexicalFrame = toLexicalFrame(exec); if (!lexicalFrame) return jsUndefined(); Frame* dynamicFrame = toDynamicFrame(exec); if (!dynamicFrame) return jsUndefined(); Page* page = frame->page(); // Because FrameTree::find() returns true for empty strings, we must check for empty framenames. // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker. if (!domWindowAllowPopUp(dynamicFrame) && (frameName.isEmpty() || !frame->tree()->find(frameName))) return jsUndefined(); // Get the target frame for the special cases of _top and _parent. In those // cases, we can schedule a location change right now and return early. bool topOrParent = false; if (frameName == "_top") { frame = frame->tree()->top(); topOrParent = true; } else if (frameName == "_parent") { if (Frame* parent = frame->tree()->parent()) frame = parent; topOrParent = true; } if (topOrParent) { String completedURL; if (!urlString.isEmpty()) completedURL = completeURL(exec, urlString).string(); if (!shouldAllowNavigation(exec, frame)) return jsUndefined(); const JSDOMWindow* targetedWindow = toJSDOMWindow(frame, currentWorld(exec)); if (!completedURL.isEmpty() && (!protocolIsJavaScript(completedURL) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) { bool userGesture = processingUserGesture(); // For whatever reason, Firefox uses the dynamicGlobalObject to // determine the outgoingReferrer. We replicate that behavior // here. String referrer = dynamicFrame->loader()->outgoingReferrer(); frame->redirectScheduler()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture); } return toJS(exec, frame->domWindow()); } // In the case of a named frame or a new window, we'll use the createWindow() helper FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0, windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0); DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect); windowFeatures.x = windowRect.x(); windowFeatures.y = windowRect.y(); windowFeatures.height = windowRect.height(); windowFeatures.width = windowRect.width(); frame = createWindow(exec, lexicalFrame, dynamicFrame, frame, urlString, frameName, windowFeatures, JSValue()); if (!frame) return jsUndefined(); return toJS(exec, frame->domWindow()); }
bool BindingSecurity::allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase* frame, const String& value) { return !protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value)) || canAccessDocument(frame->contentDocument()); }
inline bool NavigationScheduler::shouldScheduleNavigation(const String& url) const { return shouldScheduleNavigation() && (protocolIsJavaScript(url) || NavigationDisablerForBeforeUnload::isNavigationAllowed()); }
ScheduledLocationChange(Document* originDocument, const String& url, bool replacesCurrentItem) : ScheduledURLNavigation(0.0, originDocument, url, replacesCurrentItem, !protocolIsJavaScript(url)) { }
void PluginStream::startStream() { ASSERT(m_streamState == StreamBeforeStarted); const KURL& responseURL = m_resourceResponse.url(); // Some plugins (Flash) expect that javascript URLs are passed back decoded as this is the // format used when requesting the URL. if (protocolIsJavaScript(responseURL)) m_stream.url = fastStrDup(decodeURLEscapeSequences(responseURL.string()).utf8().data()); else m_stream.url = fastStrDup(responseURL.string().utf8().data()); CString mimeTypeStr = m_resourceResponse.mimeType().utf8(); long long expectedContentLength = m_resourceResponse.expectedContentLength(); if (m_resourceResponse.isHTTP()) { Vector<UChar> stringBuilder; String separator(": "); String statusLine = makeString("HTTP ", String::number(m_resourceResponse.httpStatusCode()), " OK\n"); stringBuilder.append(statusLine.characters(), statusLine.length()); HTTPHeaderMap::const_iterator end = m_resourceResponse.httpHeaderFields().end(); for (HTTPHeaderMap::const_iterator it = m_resourceResponse.httpHeaderFields().begin(); it != end; ++it) { stringBuilder.append(it->first.characters(), it->first.length()); stringBuilder.append(separator.characters(), separator.length()); stringBuilder.append(it->second.characters(), it->second.length()); stringBuilder.append('\n'); } m_headers = String::adopt(stringBuilder).utf8(); // If the content is encoded (most likely compressed), then don't send its length to the plugin, // which is only interested in the decoded length, not yet known at the moment. // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic. String contentEncoding = m_resourceResponse.httpHeaderField("Content-Encoding"); if (!contentEncoding.isNull() && contentEncoding != "identity") expectedContentLength = -1; } m_stream.headers = m_headers.data(); m_stream.pdata = 0; m_stream.ndata = this; m_stream.end = max(expectedContentLength, 0LL); m_stream.lastmodified = m_resourceResponse.lastModifiedDate(); m_stream.notifyData = m_notifyData; m_transferMode = NP_NORMAL; m_offset = 0; m_reason = WebReasonNone; // Protect the stream if destroystream is called from within the newstream handler RefPtr<PluginStream> protect(this); // calling into a plug-in could result in re-entrance if the plug-in yields // control to the system (rdar://5744899). prevent this by deferring further // loading while calling into the plug-in. if (m_loader) m_loader->setDefersLoading(true); NPError npErr = m_pluginFuncs->newstream(m_instance, (NPMIMEType)mimeTypeStr.data(), &m_stream, false, &m_transferMode); if (m_loader) m_loader->setDefersLoading(false); // If the stream was destroyed in the call to newstream we return if (m_reason != WebReasonNone) return; if (npErr != NPERR_NO_ERROR) { cancelAndDestroyStream(npErr); return; } m_streamState = StreamStarted; if (m_transferMode == NP_NORMAL) return; m_path = openTemporaryFile("WKP", m_tempFileHandle); // Something went wrong, cancel loading the stream if (!isHandleValid(m_tempFileHandle)) cancelAndDestroyStream(NPRES_NETWORK_ERR); }