1/*
2 * Copyright 2017, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.managedprovisioning.common;
17
18import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
19
20import static com.android.internal.util.Preconditions.checkNotNull;
21import static com.android.internal.util.Preconditions.checkStringNotEmpty;
22
23import android.content.Intent;
24import android.text.Html;
25import android.text.SpannableStringBuilder;
26import android.text.Spanned;
27import android.text.style.ClickableSpan;
28import android.text.style.URLSpan;
29
30import com.android.managedprovisioning.preprovisioning.WebActivity;
31
32/**
33 * Parses HTML text using {@link Html} and sets URL links to be handled by {@link WebActivity}
34 */
35public class HtmlToSpannedParser {
36    private static final int HTML_MODE = Html.FROM_HTML_MODE_COMPACT;
37
38    private final ClickableSpanFactory mClickableSpanFactory;
39    private final UrlIntentFactory mUrlIntentFactory;
40
41    /**
42     * Default constructor
43     *
44     * @param clickableSpanFactory Factory of {@link ClickableSpan} objects for urls
45     * @param urlIntentFactory Factory of {@link Intent} objects for handling urls
46     */
47    public HtmlToSpannedParser(ClickableSpanFactory clickableSpanFactory,
48            UrlIntentFactory urlIntentFactory) {
49        mClickableSpanFactory = checkNotNull(clickableSpanFactory);
50        mUrlIntentFactory = checkNotNull(urlIntentFactory);
51    }
52
53    /**
54     * See {@link Html#fromHtml(String, int)} for caveats regarding limited HTML support
55     */
56    public Spanned parseHtml(String htmlContent) {
57        Spanned spanned = Html.fromHtml(checkStringNotEmpty(htmlContent), HTML_MODE);
58        if (spanned == null) {
59            return null;
60        }
61
62        // Make html <a> tags open WebActivity
63        SpannableStringBuilder result = new SpannableStringBuilder(spanned);
64
65        URLSpan[] urlSpans = result.getSpans(0, result.length(), URLSpan.class);
66        for (URLSpan urlSpan : urlSpans) {
67            Intent intent = mUrlIntentFactory.create(urlSpan.getURL());
68            if (intent != null) {
69                int spanStart = result.getSpanStart(urlSpan);
70                int spanEnd = result.getSpanEnd(urlSpan);
71                result.setSpan(mClickableSpanFactory.create(intent), spanStart, spanEnd,
72                        SPAN_EXCLUSIVE_EXCLUSIVE);
73                result.removeSpan(urlSpan);
74            }
75        }
76
77        return result;
78    }
79
80    /**
81     * Allows to specify an intent to handle URLs
82     */
83    public interface UrlIntentFactory {
84        /**
85         * Creates an {@link Intent} based on a passed in {@link String} url
86         */
87        Intent create(String url);
88    }
89}