Search in sources :

Example 1 with CSSStyleSheetImpl

use of com.gargoylesoftware.css.dom.CSSStyleSheetImpl in project htmlunit by HtmlUnit.

the class CSSStyleSheet method loadStylesheet.

/**
 * Loads the stylesheet at the specified link or href.
 * @param element the parent DOM element
 * @param link the stylesheet's link (may be {@code null} if a <tt>url</tt> is specified)
 * @param url the stylesheet's url (may be {@code null} if a <tt>link</tt> is specified)
 * @return the loaded stylesheet
 */
public static CSSStyleSheet loadStylesheet(final HTMLElement element, final HtmlLink link, final String url) {
    final HtmlPage page = (HtmlPage) element.getDomNodeOrDie().getPage();
    String uri = page.getUrl().toExternalForm();
    try {
        // Retrieve the associated content and respect client settings regarding failing HTTP status codes.
        final WebRequest request;
        final WebResponse response;
        final WebClient client = page.getWebClient();
        if (link == null) {
            // Use href.
            final BrowserVersion browser = client.getBrowserVersion();
            request = new WebRequest(new URL(url), browser.getCssAcceptHeader(), browser.getAcceptEncodingHeader());
            request.setRefererlHeader(page.getUrl());
            // our cache is a bit strange;
            // loadWebResponse check the cache for the web response
            // AND also fixes the request url for the following cache lookups
            response = client.loadWebResponse(request);
        } else {
            // Use link.
            request = link.getWebRequest();
            if (element.getBrowserVersion().hasFeature(HTMLLINK_CHECK_TYPE_FOR_STYLESHEET)) {
                final String type = link.getTypeAttribute();
                if (StringUtils.isNotBlank(type) && !MimeType.TEXT_CSS.equals(type)) {
                    return new CSSStyleSheet(element, "", uri);
                }
            }
            // our cache is a bit strange;
            // loadWebResponse check the cache for the web response
            // AND also fixes the request url for the following cache lookups
            response = link.getWebResponse(true, request);
        }
        // now we can look into the cache with the fixed request for
        // a cached script
        final Cache cache = client.getCache();
        final Object fromCache = cache.getCachedObject(request);
        if (fromCache instanceof CSSStyleSheetImpl) {
            uri = request.getUrl().toExternalForm();
            return new CSSStyleSheet(element, element.getWindow(), (CSSStyleSheetImpl) fromCache, uri);
        }
        uri = response.getWebRequest().getUrl().toExternalForm();
        client.printContentIfNecessary(response);
        client.throwFailingHttpStatusCodeExceptionIfNecessary(response);
        // CSS content must have downloaded OK; go ahead and build the corresponding stylesheet.
        final CSSStyleSheet sheet;
        final String contentType = response.getContentType();
        if (StringUtils.isEmpty(contentType) || MimeType.TEXT_CSS.equals(contentType)) {
            final InputStream in = response.getContentAsStreamWithBomIfApplicable();
            if (in == null) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Loading stylesheet for url '" + uri + "' returns empty responseData");
                }
                return new CSSStyleSheet(element, "", uri);
            }
            try {
                Charset cssEncoding = Charset.forName("windows-1252");
                final Charset contentCharset = EncodingSniffer.sniffEncodingFromHttpHeaders(response.getResponseHeaders());
                if (contentCharset == null && request.getCharset() != null) {
                    cssEncoding = request.getCharset();
                } else if (contentCharset != null) {
                    cssEncoding = contentCharset;
                }
                if (in instanceof BOMInputStream) {
                    final BOMInputStream bomIn = (BOMInputStream) in;
                    // we have to call this before hasBOM(ByteOrderMark)
                    if (bomIn.hasBOM()) {
                        if (bomIn.hasBOM(ByteOrderMark.UTF_8)) {
                            cssEncoding = UTF_8;
                        } else if (bomIn.hasBOM(ByteOrderMark.UTF_16BE)) {
                            cssEncoding = UTF_16BE;
                        } else if (bomIn.hasBOM(ByteOrderMark.UTF_16LE)) {
                            cssEncoding = UTF_16LE;
                        }
                    }
                }
                try (InputSource source = new InputSource(new InputStreamReader(in, cssEncoding))) {
                    source.setURI(uri);
                    sheet = new CSSStyleSheet(element, source, uri);
                }
            } finally {
                in.close();
            }
        } else {
            sheet = new CSSStyleSheet(element, "", uri);
        }
        // cache the style sheet
        if (!cache.cacheIfPossible(request, response, sheet.getWrappedSheet())) {
            response.cleanUp();
        }
        return sheet;
    } catch (final FailingHttpStatusCodeException e) {
        // Got a 404 response or something like that; behave nicely.
        if (LOG.isErrorEnabled()) {
            LOG.error("Exception loading " + uri, e);
        }
        return new CSSStyleSheet(element, "", uri);
    } catch (final IOException e) {
        // Got a basic IO error; behave nicely.
        if (LOG.isErrorEnabled()) {
            LOG.error("IOException loading " + uri, e);
        }
        return new CSSStyleSheet(element, "", uri);
    } catch (final RuntimeException e) {
        // Got something unexpected; we can throw an exception in this case.
        if (LOG.isErrorEnabled()) {
            LOG.error("RuntimeException loading " + uri, e);
        }
        throw Context.reportRuntimeError("Exception: " + e);
    } catch (final Exception e) {
        // Got something unexpected; we can throw an exception in this case.
        if (LOG.isErrorEnabled()) {
            LOG.error("Exception loading " + uri, e);
        }
        throw Context.reportRuntimeError("Exception: " + e);
    }
}
Also used : InputSource(com.gargoylesoftware.css.parser.InputSource) WebResponse(com.gargoylesoftware.htmlunit.WebResponse) CSSStyleSheetImpl(com.gargoylesoftware.css.dom.CSSStyleSheetImpl) InputStreamReader(java.io.InputStreamReader) HtmlPage(com.gargoylesoftware.htmlunit.html.HtmlPage) BOMInputStream(org.apache.commons.io.input.BOMInputStream) InputStream(java.io.InputStream) Charset(java.nio.charset.Charset) IOException(java.io.IOException) WebClient(com.gargoylesoftware.htmlunit.WebClient) URL(java.net.URL) FailingHttpStatusCodeException(com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException) CSSException(com.gargoylesoftware.css.parser.CSSException) IOException(java.io.IOException) CSSParseException(com.gargoylesoftware.css.parser.CSSParseException) DOMException(org.w3c.dom.DOMException) MalformedURLException(java.net.MalformedURLException) BOMInputStream(org.apache.commons.io.input.BOMInputStream) WebRequest(com.gargoylesoftware.htmlunit.WebRequest) FailingHttpStatusCodeException(com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException) BrowserVersion(com.gargoylesoftware.htmlunit.BrowserVersion) Cache(com.gargoylesoftware.htmlunit.Cache)

Example 2 with CSSStyleSheetImpl

use of com.gargoylesoftware.css.dom.CSSStyleSheetImpl in project LoboEvolution by LoboEvolution.

the class BackgroundImageSetter method changeValue.

/**
 * {@inheritDoc}
 */
@Override
public void changeValue(AbstractCSSProperties properties, String newValue, CSSStyleDeclarationImpl declaration, boolean important) {
    String baseHref = null;
    String finalValue;
    if (declaration != null) {
        final AbstractCSSRuleImpl rule = declaration.getParentRule();
        if (rule != null) {
            final CSSStyleSheetImpl sheet = rule.getParentStyleSheet();
            final CSSStyleSheetImpl ssheet = sheet;
            baseHref = ssheet.getHref();
        }
    }
    if (baseHref == null) {
        baseHref = properties.getContext().getDocumentBaseURI();
    }
    final String start = "url(";
    if (newValue == null || !newValue.toLowerCase().startsWith(start)) {
        finalValue = newValue;
    } else {
        final int startIdx = start.length();
        final int closingIdx = newValue.lastIndexOf(')');
        if (closingIdx == -1) {
            finalValue = newValue;
        } else {
            final String quotedUri = newValue.substring(startIdx, closingIdx);
            final String tentativeUri = HtmlValues.unquoteAndUnescape(quotedUri);
            if (baseHref == null) {
                finalValue = newValue;
            } else {
                try {
                    final URL styleUrl = Urls.createURL(null, baseHref);
                    if (tentativeUri.contains("data:image")) {
                        finalValue = tentativeUri;
                    } else {
                        finalValue = "url(" + HtmlValues.quoteAndEscape(Urls.createURL(styleUrl, tentativeUri).toExternalForm()) + ")";
                    }
                } catch (final Exception mfu) {
                    logger.log(Level.WARNING, "Unable to create URL for URI=[" + tentativeUri + "], with base=[" + baseHref + "].", mfu);
                    finalValue = newValue;
                }
            }
        }
    }
    properties.setPropertyValueLCAlt(BACKGROUND_IMAGE, finalValue, important);
}
Also used : AbstractCSSRuleImpl(com.gargoylesoftware.css.dom.AbstractCSSRuleImpl) CSSStyleSheetImpl(com.gargoylesoftware.css.dom.CSSStyleSheetImpl) URL(java.net.URL)

Example 3 with CSSStyleSheetImpl

use of com.gargoylesoftware.css.dom.CSSStyleSheetImpl in project htmlunit by HtmlUnit.

the class HTMLStyleElement method getSheet.

/**
 * Gets the associated sheet.
 * @see <a href="http://www.xulplanet.com/references/objref/HTMLStyleElement.html">Mozilla doc</a>
 * @return the sheet
 */
@JsxGetter
public CSSStyleSheet getSheet() {
    if (sheet_ != null) {
        return sheet_;
    }
    final HtmlStyle style = (HtmlStyle) getDomNodeOrDie();
    final String css = style.getTextContent();
    final Window window = getWindow();
    final Cache cache = window.getWebWindow().getWebClient().getCache();
    final CSSStyleSheetImpl cached = cache.getCachedStyleSheet(css);
    final String uri = getDomNodeOrDie().getPage().getWebResponse().getWebRequest().getUrl().toExternalForm();
    if (cached != null) {
        sheet_ = new CSSStyleSheet(this, window, cached, uri);
    } else {
        sheet_ = new CSSStyleSheet(this, css, uri);
        cache.cache(css, sheet_.getWrappedSheet());
    }
    return sheet_;
}
Also used : Window(com.gargoylesoftware.htmlunit.javascript.host.Window) HtmlStyle(com.gargoylesoftware.htmlunit.html.HtmlStyle) CSSStyleSheetImpl(com.gargoylesoftware.css.dom.CSSStyleSheetImpl) CSSStyleSheet(com.gargoylesoftware.htmlunit.javascript.host.css.CSSStyleSheet) Cache(com.gargoylesoftware.htmlunit.Cache) JsxGetter(com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter)

Example 4 with CSSStyleSheetImpl

use of com.gargoylesoftware.css.dom.CSSStyleSheetImpl in project htmlunit by HtmlUnit.

the class CSSStyleSheet method parseCSS.

/**
 * Parses the CSS at the specified input source. If anything at all goes wrong, this method
 * returns an empty stylesheet.
 *
 * @param source the source from which to retrieve the CSS to be parsed
 * @param client the client
 * @return the stylesheet parsed from the specified input source
 */
private static CSSStyleSheetImpl parseCSS(final InputSource source, final WebClient client) {
    CSSStyleSheetImpl ss;
    try {
        final CSSErrorHandler errorHandler = client.getCssErrorHandler();
        final CSSOMParser parser = new CSSOMParser(new CSS3Parser());
        parser.setErrorHandler(errorHandler);
        ss = parser.parseStyleSheet(source, null);
    } catch (final Throwable t) {
        if (LOG.isErrorEnabled()) {
            LOG.error("Error parsing CSS from '" + toString(source) + "': " + t.getMessage(), t);
        }
        ss = new CSSStyleSheetImpl();
    }
    return ss;
}
Also used : CSSStyleSheetImpl(com.gargoylesoftware.css.dom.CSSStyleSheetImpl) CSSErrorHandler(com.gargoylesoftware.css.parser.CSSErrorHandler) CSSOMParser(com.gargoylesoftware.css.parser.CSSOMParser) CSS3Parser(com.gargoylesoftware.css.parser.javacc.CSS3Parser)

Example 5 with CSSStyleSheetImpl

use of com.gargoylesoftware.css.dom.CSSStyleSheetImpl in project htmlunit by HtmlUnit.

the class CSSStyleSheet method getRuleIndex.

private CSSStyleSheetImpl.CSSStyleSheetRuleIndex getRuleIndex() {
    final CSSStyleSheetImpl styleSheet = getWrappedSheet();
    CSSStyleSheetImpl.CSSStyleSheetRuleIndex index = styleSheet.getRuleIndex();
    if (index == null) {
        index = new CSSStyleSheetImpl.CSSStyleSheetRuleIndex();
        final CSSRuleListImpl ruleList = styleSheet.getCssRules();
        index(index, ruleList, new HashSet<>());
        styleSheet.setRuleIndex(index);
    }
    return index;
}
Also used : CSSStyleSheetImpl(com.gargoylesoftware.css.dom.CSSStyleSheetImpl) CSSRuleListImpl(com.gargoylesoftware.css.dom.CSSRuleListImpl)

Aggregations

CSSStyleSheetImpl (com.gargoylesoftware.css.dom.CSSStyleSheetImpl)5 Cache (com.gargoylesoftware.htmlunit.Cache)2 URL (java.net.URL)2 AbstractCSSRuleImpl (com.gargoylesoftware.css.dom.AbstractCSSRuleImpl)1 CSSRuleListImpl (com.gargoylesoftware.css.dom.CSSRuleListImpl)1 CSSErrorHandler (com.gargoylesoftware.css.parser.CSSErrorHandler)1 CSSException (com.gargoylesoftware.css.parser.CSSException)1 CSSOMParser (com.gargoylesoftware.css.parser.CSSOMParser)1 CSSParseException (com.gargoylesoftware.css.parser.CSSParseException)1 InputSource (com.gargoylesoftware.css.parser.InputSource)1 CSS3Parser (com.gargoylesoftware.css.parser.javacc.CSS3Parser)1 BrowserVersion (com.gargoylesoftware.htmlunit.BrowserVersion)1 FailingHttpStatusCodeException (com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException)1 WebClient (com.gargoylesoftware.htmlunit.WebClient)1 WebRequest (com.gargoylesoftware.htmlunit.WebRequest)1 WebResponse (com.gargoylesoftware.htmlunit.WebResponse)1 HtmlPage (com.gargoylesoftware.htmlunit.html.HtmlPage)1 HtmlStyle (com.gargoylesoftware.htmlunit.html.HtmlStyle)1 JsxGetter (com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter)1 Window (com.gargoylesoftware.htmlunit.javascript.host.Window)1