前几天,项目组有个技术问题,想用本地加载html, js写cookie的方法,绕过去。

想法是没有问题的, 但是测试的时候发现, 每次重新打开App, 都取不到以前Cookie里面设的值。

后来去App/data下面找WebView.db,打开来一看,cookie情报根本没有存。

原因是js写cookie的时候,没有指明expire, WebKit默认把它当成临时cookie, webview终了之后就丢失了。

这个问题本身不复杂,不过趁机我看了一把Andorid底层读取Cookie的source root:

以下source root

1. 取Cookie的API

[java] view plain copy print ?
  1. CookieManager.getInstance().getCookie(url);
CookieManager.getInstance().getCookie(url);

2.CookieManager的getInstance()

[java] view plain copy print ?
  1. /**
  2. * Gets the singleton CookieManager instance. If this method is used
  3. * before the application instantiates a {@link WebView} instance,
  4. * {@link CookieSyncManager#createInstance(Context)} must be called
  5. * first.
  6. *
  7. * @return the singleton CookieManager instance
  8. */
  9. publicstaticsynchronized CookieManager getInstance() {
  10. return WebViewFactory.getProvider().getCookieManager();
  11. }
 /**     * Gets the singleton CookieManager instance. If this method is used     * before the application instantiates a {@link WebView} instance,     * {@link CookieSyncManager#createInstance(Context)} must be called     * first.     *     * @return the singleton CookieManager instance     */    public static synchronized CookieManager getInstance() {        return WebViewFactory.getProvider().getCookieManager();    }
3.WebViewFactory是个工厂模式,额

[java] view plain copy print ?
  1. staticsynchronized WebViewFactoryProvider getProvider() {
  2. // For now the main purpose of this function (and the factory abstraction) is to keep
  3. // us honest and minimize usage of WebViewClassic internals when binding the proxy.
  4. if (sProviderInstance != null) return sProviderInstance;
  5. sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);
  6. if (sProviderInstance == null) {
  7. if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
  8. sProviderInstance = new WebViewClassic.Factory();
  9. }
  10. return sProviderInstance;
  11. }
    static synchronized WebViewFactoryProvider getProvider() {        // For now the main purpose of this function (and the factory abstraction) is to keep        // us honest and minimize usage of WebViewClassic internals when binding the proxy.        if (sProviderInstance != null) return sProviderInstance;        sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);        if (sProviderInstance == null) {            if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");            sProviderInstance = new WebViewClassic.Factory();        }        return sProviderInstance;    }
4.层层嵌套,最后生成的instance是CookieManagerClassic

[java] view plain copy print ?
  1. @Override
  2. public CookieManager getCookieManager() {
  3. return CookieManagerClassic.getInstance();
  4. }
 @Override        public CookieManager getCookieManager() {            return CookieManagerClassic.getInstance();        }
5. getCookie方法 实现在CookieManagerClassic上

[java] view plain copy print ?
  1. @Override
  2. public String getCookie(String url) {
  3. return getCookie(url, false);
  4. }
  5. @Override
  6. public String getCookie(String url, boolean privateBrowsing) {
  7. WebAddress uri;
  8. try {
  9. uri = new WebAddress(url);
  10. } catch (ParseException ex) {
  11. Log.e(LOGTAG, "Bad address: " + url);
  12. returnnull;
  13. }
  14. return nativeGetCookie(uri.toString(), privateBrowsing);
  15. }
  @Override    public String getCookie(String url) {        return getCookie(url, false);    }    @Override    public String getCookie(String url, boolean privateBrowsing) {        WebAddress uri;        try {            uri = new WebAddress(url);        } catch (ParseException ex) {            Log.e(LOGTAG, "Bad address: " + url);            return null;        }        return nativeGetCookie(uri.toString(), privateBrowsing);    }
6. nativeGetCookie定义在CookieManager.cpp里, 恩。。。。JNI。。。

[java] view plain copy print ?
  1. static jstring getCookie(JNIEnv* env, jobject, jstring url, jboolean privateBrowsing)
  2. {
  3. GURL gurl(jstringToStdString(env, url));
  4. CookieOptions options;
  5. options.set_include_httponly();
  6. std::string cookies = WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->GetCookiesWithOptions(gurl, options);
  7. return stdStringToJstring(env, cookies);
  8. }
static jstring getCookie(JNIEnv* env, jobject, jstring url, jboolean privateBrowsing){    GURL gurl(jstringToStdString(env, url));    CookieOptions options;    options.set_include_httponly();    std::string cookies = WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->GetCookiesWithOptions(gurl, options);    return stdStringToJstring(env, cookies);}
7. WebCookieJar.cpp中,定义了从哪里去取得Cookie情报

[java] view plain copy print ?
  1. WebCookieJar* WebCookieJar::get(bool isPrivateBrowsing)
  2. {
  3. MutexLocker lock(instanceMutex);
  4. if (!isFirstInstanceCreated && fileSchemeCookiesEnabled)
  5. net::CookieMonster::EnableFileScheme();
  6. isFirstInstanceCreated = true;
  7. scoped_refptr<WebCookieJar>* instancePtr = instance(isPrivateBrowsing);
  8. if (!instancePtr->get())
  9. *instancePtr = new WebCookieJar(databaseDirectory(isPrivateBrowsing));
  10. return instancePtr->get();
  11. }
WebCookieJar* WebCookieJar::get(bool isPrivateBrowsing){    MutexLocker lock(instanceMutex);    if (!isFirstInstanceCreated && fileSchemeCookiesEnabled)        net::CookieMonster::EnableFileScheme();    isFirstInstanceCreated = true;    scoped_refptr<WebCookieJar>* instancePtr = instance(isPrivateBrowsing);    if (!instancePtr->get())        *instancePtr = new WebCookieJar(databaseDirectory(isPrivateBrowsing));    return instancePtr->get();}
[java] view plain copy print ?
  1. static std::string databaseDirectory(bool isPrivateBrowsing)
  2. {
  3. staticconstchar* const kDatabaseFilename = "/webviewCookiesChromium.db";
  4. staticconstchar* const kDatabaseFilenamePrivateBrowsing = "/webviewCookiesChromiumPrivate.db";
  5. std::string databaseFilePath = databaseDirectory();
  6. databaseFilePath.append(isPrivateBrowsing ? kDatabaseFilenamePrivateBrowsing : kDatabaseFilename);
  7. return databaseFilePath;
  8. }
static std::string databaseDirectory(bool isPrivateBrowsing){    static const char* const kDatabaseFilename = "/webviewCookiesChromium.db";    static const char* const kDatabaseFilenamePrivateBrowsing = "/webviewCookiesChromiumPrivate.db";    std::string databaseFilePath = databaseDirectory();    databaseFilePath.append(isPrivateBrowsing ? kDatabaseFilenamePrivateBrowsing : kDatabaseFilename);    return databaseFilePath;}
※Android3.0以上是webviewCookiesChromium.db, 以下是WebView.db文件

8.最后读取Cookie情报发生在cookie_monster.cc。 额,最后调到C++, 去读.db文件,无敌了

[java] view plain copy print ?
  1. std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
  2. const CookieOptions& options) {
  3. base::AutoLock autolock(lock_);
  4. InitIfNecessary();
  5. if (!HasCookieableScheme(url)) {
  6. return std::string();
  7. }
  8. TimeTicks start_time(TimeTicks::Now());
  9. // Get the cookies for this host and its domain(s).
  10. std::vector<CanonicalCookie*> cookies;
  11. FindCookiesForHostAndDomain(url, options, true, &cookies);
  12. std::sort(cookies.begin(), cookies.end(), CookieSorter);
  13. std::string cookie_line;
  14. for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
  15. it != cookies.end(); ++it) {
  16. if (it != cookies.begin())
  17. cookie_line += "; ";
  18. // In Mozilla if you set a cookie like AAAA, it will have an empty token
  19. // and a value of AAAA. When it sends the cookie back, it will send AAAA,
  20. // so we need to avoid sending =AAAA for a blank token value.
  21. if (!(*it)->Name().empty())
  22. cookie_line += (*it)->Name() + "=";
  23. cookie_line += (*it)->Value();
  24. }
  25. histogram_time_get_->AddTime(TimeTicks::Now() - start_time);
  26. VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
  27. return cookie_line;
  28. }
std::string CookieMonster::GetCookiesWithOptions(const GURL& url,                                                 const CookieOptions& options) {  base::AutoLock autolock(lock_);  InitIfNecessary();  if (!HasCookieableScheme(url)) {    return std::string();  }  TimeTicks start_time(TimeTicks::Now());  // Get the cookies for this host and its domain(s).  std::vector<CanonicalCookie*> cookies;  FindCookiesForHostAndDomain(url, options, true, &cookies);  std::sort(cookies.begin(), cookies.end(), CookieSorter);  std::string cookie_line;  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();       it != cookies.end(); ++it) {    if (it != cookies.begin())      cookie_line += "; ";    // In Mozilla if you set a cookie like AAAA, it will have an empty token    // and a value of AAAA.  When it sends the cookie back, it will send AAAA,    // so we need to avoid sending =AAAA for a blank token value.    if (!(*it)->Name().empty())      cookie_line += (*it)->Name() + "=";    cookie_line += (*it)->Value();  }  histogram_time_get_->AddTime(TimeTicks::Now() - start_time);  VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;  return cookie_line;}
#以上#

更多相关文章

  1. Android(安卓)Retrofit 源码系列(二)~ 自定义 CallAdapter
  2. android6.0获取通讯录权限
  3. [android UI]自定义各种UI,收集在此,以备后用!
  4. Android(安卓)自定义弹窗提示
  5. 基于Android的Word在线预览
  6. Android(安卓)自定义适配器
  7. Android的Shape图片资源,用于做些自定义样式的按钮等。
  8. Android自定义布局通知栏
  9. 细节决定成败----Android应用程序的优化(四)

随机推荐

  1. 学习,是脱贫致富的捷径
  2. HBase协处理器加载的三种方式
  3. 是时候丢掉 onActivityResult 了 !
  4. 为什么说for...of是JS中的一颗宝石
  5. 很多人不知道的Python 炫技操作:合并字典
  6. 一文带你入门Java Stream流,太强了
  7. 中心化交易所和去中心化交易所优势分别在
  8. 一文让你彻底掌握 TS 枚举
  9. 我去,你写的 switch 语句也太老土了吧
  10. 从 SQL 到 MongoDB,这一篇就够了