英文狀態(tài)下CookieManager setCookie Expires字段的識(shí)別

CookieManager cookieManager = CookieManager.getInstance();
String domain = ".bilibili.com";
String cookie1 = "bili_jct=b33fd713ea7cc6d29d65462794b28441; Domain=.bilibili.com; Expires=Expires=Sun, 18 Jan 1970 22:11:45 GMT+08:00";
String cookie2 = "bili_jct=49b9bcc2c21f19cc9dcb8382b84cf552; Domain=.bilibili.com; Expires=Expires=周日, 18 1月 1970 22:11:40 GMT+08:00";
cookieManager.setCookie(domain, cookie1);
String cookie1R = cookieManager.getCookie(domain);
Log.i("Cookie","load cookie1 "+cookie1R);
cookieManager.setCookie(domain, cookie2);
String cookie2R = cookieManager.getCookie(domain);
Log.i("Cookie","load cookie1 "+cookie2R);

輸出

: load cookie1 null
: load cookie1 bili_jct=49b9bcc2c21f19cc9dcb8382b84cf552

問(wèn)題原因就是英文狀態(tài)是會(huì)識(shí)別Expires岖妄,所以在存入cookie1后CookieManager會(huì)認(rèn)為這個(gè)cookie是過(guò)期的,所以會(huì)忽略掉這個(gè)cookie,返回null,但是在中文是不會(huì)識(shí)別Expires咏闪,所以可以返回cookie.
我嘗試去跟蹤了一下源碼去發(fā)現(xiàn)為什么會(huì)出現(xiàn)這種情況

public abstract class CookieManager{
       public abstract void setCookie(String url, String value);
}

CookieManager是一個(gè)抽象類,setCookie也是一個(gè)抽象方法,所以必需找到其實(shí)現(xiàn)類

public static CookieManager getInstance() {
        return WebViewFactory.getProvider().getCookieManager();
}

進(jìn)入getProvider

static WebViewFactoryProvider getProvider() {
        synchronized (sProviderLock) {
            // For now the main purpose of this function (and the factory abstraction) is to keep
            // us honest and minimize usage of WebView internals when binding the proxy.
            if (sProviderInstance != null) return sProviderInstance;
            //代碼省略
            try {
                Class<WebViewFactoryProvider> providerClass = getProviderClass();
                Method staticFactory = null;
                try {
                    staticFactory = providerClass.getMethod(
                        CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class);
                } catch (Exception e) {
                    if (DEBUG) {
                        Log.w(LOGTAG, "error instantiating provider with static factory method", e);
                    }
                }

                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
                try {
                    sProviderInstance = (WebViewFactoryProvider)
                            staticFactory.invoke(null, new WebViewDelegate());
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    Log.e(LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }
    }

可以看到sProviderInstance就是我們要的WebViewFactoryProvider,WebViewFactoryProvider是一個(gè)接口备图,它的創(chuàng)建實(shí)際上分為兩步。

第一步:獲取工廠類赶袄,這個(gè)工廠是用來(lái)創(chuàng)建WebViewFactoryProvider的實(shí)現(xiàn)類.
 Class<WebViewFactoryProvider> providerClass = getProviderClass();
private static Class<WebViewFactoryProvider> getProviderClass() {
        //代碼省略
       ClassLoader clazzLoader = webViewContext.getClassLoader();
       return getWebViewProviderClass(clazzLoader);
}
public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
            throws ClassNotFoundException {
        return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
                true, clazzLoader);
    }
private static final String CHROMIUM_WEBVIEW_FACTORY =
            "com.android.webview.chromium.WebViewChromiumFactoryProviderForO";

WebViewChromiumFactoryProviderForO就是目前獲取的工廠類.

第二步:通過(guò)WebViewFactoryProvider的工廠類(現(xiàn)在已經(jīng)知道了是WebViewChromiumFactoryProviderForO)創(chuàng)建WebViewFactoryProvider的實(shí)現(xiàn)類

再回到getProvider中看看下面這些代碼:

                Method staticFactory = null;
                try {
                    staticFactory = providerClass.getMethod(
                        CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class);
                } catch (Exception e) {
                    if (DEBUG) {
                        Log.w(LOGTAG, "error instantiating provider with static factory method", e);
                    }
                }

                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
                try {
                    sProviderInstance = (WebViewFactoryProvider)
                            staticFactory.invoke(null, new WebViewDelegate());

可以看出來(lái)它是通過(guò)反射WebViewChromiumFactoryProviderForO的CHROMIUM_WEBVIEW_FACTORY_METHOD方法獲取WebViewFactoryProvider的實(shí)現(xiàn)類.

private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";

源碼中的CHROMIUM_WEBVIEW_FACTORY_METHOD是一個(gè)create函數(shù).

Ok,我們現(xiàn)在找到了WebViewFactoryProvider的實(shí)現(xiàn)類是通過(guò)高反射WebViewChromiumFactoryProviderForO調(diào)用create創(chuàng)建的揽涮,那下面來(lái)看看WebViewChromiumFactoryProviderForO的源碼怎么實(shí)現(xiàn)create.

class WebViewChromiumFactoryProviderForO extends WebViewChromiumFactoryProvider {
    public static WebViewChromiumFactoryProvider create(android.webkit.WebViewDelegate delegate) {
        return new WebViewChromiumFactoryProviderForO(delegate);
    }

    protected WebViewChromiumFactoryProviderForO(android.webkit.WebViewDelegate delegate) {
        super(delegate);
    }
}

可以看出來(lái)WebViewChromiumFactoryProviderForO的create方法創(chuàng)建的其實(shí)就是它自己,但是它的很多方法都是在父類里面的饿肺,我們需要跟進(jìn)父類去看看getCookieManager到底返回的是什么蒋困,才能知道CookieManager的實(shí)現(xiàn)類是什么.

public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider {
@Override
    public CookieManager getCookieManager() {
        synchronized (mLock) {
            if (mCookieManager == null) {
                if (!mStarted) {
                    // We can use CookieManager without starting Chromium; the native code
                    // will bring up just the parts it needs to make this work on a temporary
                    // basis until Chromium is started for real. The temporary cookie manager
                    // needs the application context to have been set.
                    ContentMain.initApplicationContext(mWebViewDelegate.getApplication());
                }
                mCookieManager = new CookieManagerAdapter(new AwCookieManager());
            }
        }
        return mCookieManager;
    }
}

WebViewChromiumFactoryProvider中的getCookieManager返回的是一個(gè)CookieManagerAdapter,這里終于找到了CookieManager的實(shí)現(xiàn)類是CookieManagerAdapter
繼續(xù)看看CookieManagerAdapter的setCookie函數(shù)怎么實(shí)現(xiàn)的

public class CookieManagerAdapter extends CookieManager {

AwCookieManager mChromeCookieManager;

@Override
    public void setCookie(String url, String value) {
        try {
            mChromeCookieManager.setCookie(fixupUrl(url), value);
        } catch (ParseException e) {
            Log.e(LOGTAG, "Not setting cookie due to error parsing URL: " + url, e);
        }
    }
}
@JNINamespace("android_webview")
public final class AwCookieManager {
    /**
     * Set cookie for a given url. The old cookie with same host/path/name will
     * be removed. The new cookie will be added if it is not expired or it does
     * not have expiration which implies it is session cookie.
     * @param url The url which cookie is set for
     * @param value The value for set-cookie: in http response header
     */
   public void setCookie(final String url, final String value) {
        nativeSetCookie(url, value);
    }
   private native void nativeSetCookie(String url, String value);
}

最終走到了一個(gè)nativeSetCookie方法敬辣,它是native方法. so,目前暫時(shí)也沒(méi)有辦法跟進(jìn)了,目前只能從注釋推斷這其實(shí)中文情況下面expiration是無(wú)效的.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雪标,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子溉跃,更是在濱河造成了極大的恐慌村刨,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撰茎,死亡現(xiàn)場(chǎng)離奇詭異嵌牺,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乾吻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門髓梅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绎签,你說(shuō)我怎么就攤上這事枯饿。” “怎么了诡必?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵奢方,是天一觀的道長(zhǎng)搔扁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蟋字,這世上最難降的妖魔是什么孤钦? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任沪曙,我火速辦了婚禮贿讹,結(jié)果婚禮上养篓,老公的妹妹穿的比我還像新娘。我一直安慰自己忠聚,他們只是感情好设哗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著两蟀,像睡著了一般网梢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赂毯,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天战虏,我揣著相機(jī)與錄音,去河邊找鬼党涕。 笑死烦感,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遣鼓。 我是一名探鬼主播啸盏,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼重贺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼骑祟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起气笙,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤次企,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后潜圃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缸棵,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年谭期,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堵第。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隧出,死狀恐怖踏志,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胀瞪,我是刑警寧澤针余,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響圆雁,放射性物質(zhì)發(fā)生泄漏忍级。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一伪朽、第九天 我趴在偏房一處隱蔽的房頂上張望轴咱。 院中可真熱鬧,春花似錦烈涮、人聲如沸嗦玖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宇挫。三九已至,卻和暖如春酪术,著一層夾襖步出監(jiān)牢的瞬間器瘪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工绘雁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留橡疼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓庐舟,卻偏偏與公主長(zhǎng)得像欣除,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挪略,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容