日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android平台Chromium net中的代理配置信息获取

發(fā)布時間:2024/4/11 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android平台Chromium net中的代理配置信息获取 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在計算機網(wǎng)絡(luò)中,代理服務(wù)器 扮演著發(fā)起請求的客戶端與服務(wù)器之間的中間人的角色。客戶端連接到代理服務(wù)器,請求一些服務(wù),比如文件,網(wǎng)頁,或其它可以從服務(wù)器獲得的資源,代理服務(wù)器以簡化和控制復雜度的形式獲取請求的響應(yīng)。代理被發(fā)明以為分布式系統(tǒng)添加結(jié)構(gòu)和封裝。

在我們做移動端開發(fā)時,代理常常可以作為我們網(wǎng)絡(luò)調(diào)試的利器。然而我們設(shè)置的代理究竟是如何對網(wǎng)絡(luò)訪問的整個過程產(chǎn)生影響的呢?本文將嘗試回答這個問題。

系統(tǒng)靜態(tài)代理服務(wù)器信息的解析

一個HTTP請求的執(zhí)行過程,大體為:

  • 連接準備。
  • 建立TCP連接。
  • 如果是HTTPS的話,完成SSL/TLS的握手。
  • 如果是HTTP2的話,在SSL/TLS握手完成之后,執(zhí)行HTTP2的協(xié)商。
  • 發(fā)送請求。
  • 獲取響應(yīng)。
  • 結(jié)束請求,關(guān)閉連接。
  • 與代理相關(guān)的處理,主要發(fā)生在上面的連接準備與連接建立階段,這主要包括解析系統(tǒng)中保存的靜態(tài)代理服務(wù)器設(shè)置信息,以及以特有的方式建立與代理之間的連接。

    Chromium net在 HttpStreamFactoryImpl::Job::DoLoop(int result) 中執(zhí)行解析代理信息、建立連接、處理TLS握手/HTTP2握手/QUIC握手,并創(chuàng)建Stream的過程:

    int HttpStreamFactoryImpl::Job::DoLoop(int result) {DCHECK_NE(next_state_, STATE_NONE);int rv = result;do {State state = next_state_;next_state_ = STATE_NONE;switch (state) {case STATE_START:DCHECK_EQ(OK, rv);rv = DoStart();break;case STATE_RESOLVE_PROXY:DCHECK_EQ(OK, rv);rv = DoResolveProxy();break;case STATE_RESOLVE_PROXY_COMPLETE:rv = DoResolveProxyComplete(rv);break;case STATE_WAIT:DCHECK_EQ(OK, rv);rv = DoWait();break;case STATE_WAIT_COMPLETE:rv = DoWaitComplete(rv);break;case STATE_INIT_CONNECTION:DCHECK_EQ(OK, rv);rv = DoInitConnection();break;case STATE_INIT_CONNECTION_COMPLETE:rv = DoInitConnectionComplete(rv);break;case STATE_WAITING_USER_ACTION:rv = DoWaitingUserAction(rv);break;case STATE_RESTART_TUNNEL_AUTH:DCHECK_EQ(OK, rv);rv = DoRestartTunnelAuth();break;case STATE_RESTART_TUNNEL_AUTH_COMPLETE:rv = DoRestartTunnelAuthComplete(rv);break;

    具體到系統(tǒng)靜態(tài)代理服務(wù)器設(shè)置信息的解析,

    int HttpStreamFactoryImpl::Job::DoResolveProxy() {DCHECK(!pac_request_);DCHECK(session_);next_state_ = STATE_RESOLVE_PROXY_COMPLETE;if (request_info_.load_flags & LOAD_BYPASS_PROXY) {proxy_info_.UseDirect();return OK;}// TODO(rch): remove this code since Alt-Svc seems to prohibit it.GURL url_for_proxy = origin_url_;// For SPDY via Alt-Svc, set |alternative_service_url_| to// https://<alternative host>:<alternative port>/...// so the proxy resolution works with the actual destination, and so// that the correct socket pool is used.if (IsSpdyAlternative()) {// TODO(rch): Figure out how to make QUIC iteract with PAC// scripts. By not re-writing the URL, we will query the PAC script// for the proxy to use to reach the original URL via TCP. But// the alternate request will be going via UDP to a different port.GURL::Replacements replacements;// new_port needs to be in scope here because GURL::Replacements references// the memory contained by it directly.const std::string new_port = base::UintToString(alternative_service_.port);replacements.SetSchemeStr("https");replacements.SetPortStr(new_port);url_for_proxy = url_for_proxy.ReplaceComponents(replacements);}return session_->proxy_service()->ResolveProxy(url_for_proxy, request_info_.method, &proxy_info_, io_callback_,&pac_request_, session_->params().proxy_delegate, net_log_); }int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {pac_request_ = NULL;if (result == OK) {// Remove unsupported proxies from the list.int supported_proxies =ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP |ProxyServer::SCHEME_HTTPS | ProxyServer::SCHEME_SOCKS4 |ProxyServer::SCHEME_SOCKS5;if (session_->params().enable_quic)supported_proxies |= ProxyServer::SCHEME_QUIC;proxy_info_.RemoveProxiesWithoutScheme(supported_proxies);if (proxy_info_.is_empty()) {// No proxies/direct to choose from. This happens when we don't support// any of the proxies in the returned list.result = ERR_NO_SUPPORTED_PROXIES;} else if (using_quic_ &&(!proxy_info_.is_quic() && !proxy_info_.is_direct())) {// QUIC can not be spoken to non-QUIC proxies. This error should not be// user visible, because the non-alternative Job should be resumed.result = ERR_NO_SUPPORTED_PROXIES;}}if (result != OK) {return result;}next_state_ = STATE_WAIT;return OK; }

    Chromium net在對請求的代理的處理上比較靈活,它允許為請求設(shè)置一個標記 LOAD_BYPASS_PROXY ,以使該請求的執(zhí)行總是繞過代理。在HttpStreamFactoryImpl::Job::DoResolveProxy() 中會首先檢查請求是否設(shè)置了這個標記,若設(shè)置,則將與服務(wù)器直連而立即返回,不再執(zhí)行后面解析系統(tǒng)代理服務(wù)器設(shè)置系統(tǒng)的過程。否則繼續(xù)執(zhí)行。

    對于代理的使用,用戶通常都可以設(shè)置一些規(guī)則,比如代理的類型,比如對設(shè)置對某些域名的訪問不使用代理等等。因而對于適當?shù)拇淼倪x擇,是根據(jù)設(shè)置的規(guī)則和要訪問的URL進行的。Alternative-Service是一種用于支持新協(xié)議,比如HTTP2,SPDY和QUIC這種,的機制。這種機制通過服務(wù)器向客戶端返回一個 "Alt-Svc" 頭部字段以表明服務(wù)器期望客戶端采用的新協(xié)議。如果要使用新協(xié)議,則發(fā)送請求的URL可能會有一定的改變。在HttpStreamFactoryImpl::Job::DoResolveProxy() 中,若要使用 "Alt-Svc" SPDY/HTTP2,會先對原始的Url做一定的修飾,并以修飾后的Url為基礎(chǔ)去選擇代理。

    最后通過ProxyService解析代理信息,選擇代理服務(wù)器。

    解析代理之后,執(zhí)行的HttpStreamFactoryImpl::Job::DoResolveProxyComplete() 主要是對解析的結(jié)果做檢查。在這里會過濾掉不支持的代理,并返回最終的檢查結(jié)果。為了保持處理邏輯的簡便統(tǒng)一,即使沒有設(shè)置任何代理服務(wù)器,解析的代理服務(wù)器列表也不會是空的,而是包含一個類型為DIRECT的代理設(shè)置。

    默認的ProxyService

    HttpStreamFactoryImpl::Job::DoResolveProxy() 所用到的 ProxyService 來自于HttpNetworkSession。而 HttpNetworkSession 的 ProxyService 則是通過如下過程一步一步從 URLRequestContextBuilder 傳過來的:

    HttpStreamFactoryImpl::Job::Job() <- DefaultJobFactory::CreateJob() <- HttpStreamFactoryImpl::HttpStreamFactoryImpl() <- HttpNetworkSession::HttpNetworkSession(const Params& params) <- URLRequestContextBuilder::Build()

    在 URLRequestContextBuilder::Build() 中可以看到如下的幾行代碼:

    void URLRequestContextBuilder::SetHttpNetworkSessionComponents(const URLRequestContext* context,HttpNetworkSession::Params* params) {params->host_resolver = context->host_resolver();params->cert_verifier = context->cert_verifier();params->transport_security_state = context->transport_security_state();params->cert_transparency_verifier = context->cert_transparency_verifier();params->ct_policy_enforcer = context->ct_policy_enforcer();params->proxy_service = context->proxy_service();params->ssl_config_service = context->ssl_config_service();params->http_auth_handler_factory = context->http_auth_handler_factory();params->http_server_properties = context->http_server_properties();params->net_log = context->net_log();params->channel_id_service = context->channel_id_service(); } . . . . . . std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {std::unique_ptr<ContainerURLRequestContext> context(new ContainerURLRequestContext(file_task_runner_));URLRequestContextStorage* storage = context->storage(); . . . . . .if (!proxy_service_) {// TODO(willchan): Switch to using this code when// ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck. #if !defined(OS_LINUX) && !defined(OS_ANDROID)if (!proxy_config_service_) {proxy_config_service_ = ProxyService::CreateSystemProxyConfigService(base::ThreadTaskRunnerHandle::Get().get(),context->GetFileTaskRunner());} #endif // !defined(OS_LINUX) && !defined(OS_ANDROID)proxy_service_ = ProxyService::CreateUsingSystemProxyResolver(std::move(proxy_config_service_),0, // This results in using the default value.context->net_log());}storage->set_proxy_service(std::move(proxy_service_));

    然而,對于Android而言,使用的并不是這里創(chuàng)建的 ProxyService 。ProxyConfigService 和 ProxyService 都是在更早的時候創(chuàng)建的。ProxyConfigService 創(chuàng)建的位置 (components/cronet/android/cronet_url_request_context_adapter.cc) 如下:

    void CronetURLRequestContextAdapter::InitRequestContextOnMainThread(JNIEnv* env,const JavaParamRef<jobject>& jcaller) {base::android::ScopedJavaGlobalRef<jobject> jcaller_ref;jcaller_ref.Reset(env, jcaller);proxy_config_service_ = net::ProxyService::CreateSystemProxyConfigService(GetNetworkTaskRunner(), nullptr /* Ignored on Android */);net::ProxyConfigServiceAndroid* android_proxy_config_service =static_cast<net::ProxyConfigServiceAndroid*>(proxy_config_service_.get());// If a PAC URL is present, ignore it and use the address and port of// Android system's local HTTP proxy server. See: crbug.com/432539.// TODO(csharrison) Architect the wrapper better so we don't need to cast for// android ProxyConfigServices.android_proxy_config_service->set_exclude_pac_url(true);g_net_log.Get().EnsureInitializedOnMainThread();GetNetworkTaskRunner()->PostTask(FROM_HERE,base::Bind(&CronetURLRequestContextAdapter::InitializeOnNetworkThread,base::Unretained(this), base::Passed(&context_config_),jcaller_ref)); }

    而 ProxyService 的創(chuàng)建位置 (components/cronet/android/cronet_url_request_context_adapter.cc) 則在 CronetURLRequestContextAdapter::InitializeOnNetworkThread():

    void CronetURLRequestContextAdapter::InitializeOnNetworkThread(std::unique_ptr<URLRequestContextConfig> config,const base::android::ScopedJavaGlobalRef<jobject>&jcronet_url_request_context) {DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());DCHECK(!is_context_initialized_);DCHECK(proxy_config_service_);// TODO(mmenke): Add method to have the builder enable SPDY.net::URLRequestContextBuilder context_builder;std::unique_ptr<net::NetworkDelegate> network_delegate(new BasicNetworkDelegate()); #if defined(DATA_REDUCTION_PROXY_SUPPORT) . . . . . . #endif // defined(DATA_REDUCTION_PROXY_SUPPORT)context_builder.set_network_delegate(std::move(network_delegate));context_builder.set_net_log(g_net_log.Get().net_log());// Android provides a local HTTP proxy server that handles proxying when a PAC// URL is present. Create a proxy service without a resolver and rely on this// local HTTP proxy. See: crbug.com/432539.context_builder.set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(std::move(proxy_config_service_), g_net_log.Get().net_log()));

    ProxyConfigService 和 ProxyService 的實際創(chuàng)建過程(位于net/proxy/proxy_service.cc )如下:

    // static std::unique_ptr<ProxyService> ProxyService::CreateWithoutProxyResolver(std::unique_ptr<ProxyConfigService> proxy_config_service,NetLog* net_log) {return base::WrapUnique(new ProxyService(std::move(proxy_config_service),base::WrapUnique(new ProxyResolverFactoryForNullResolver), net_log)); } . . . . . . // static std::unique_ptr<ProxyConfigService> ProxyService::CreateSystemProxyConfigService(const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) { #if defined(OS_WIN) . . . . . . #elif defined(OS_ANDROID)return base::WrapUnique(new ProxyConfigServiceAndroid(io_task_runner, base::ThreadTaskRunnerHandle::Get())); #elseLOG(WARNING) << "Failed to choose a system proxy settings fetcher ""for this platform.";return base::WrapUnique(new ProxyConfigServiceDirect()); #endif }

    可見在Android平臺,默認的ProxyConfigService 為 ProxyConfigServiceAndroid, ProxyService 本身并不單單是接口,它在解析代理信息時,除了依賴靜態(tài)信息外,還會依賴 ProxyResolverFactory 和 ProxyResolver 去獲得代理信息。按照設(shè)計, ProxyResolver 將會填充用于特定URL的代理的列表。通常的 ProxyResolver 后端都是一個PAC腳本,但也不一定。一個 ProxyResolver 可以在同一時間為多個URL服務(wù)。

    而在Android平臺 ProxyResolverFactory 和 ProxyResolver 的實現(xiàn)分別為 ProxyResolverFactoryForNullResolver 和 ProxyResolverNull。可以看一下ProxyResolverFactoryForNullResolver 和 ProxyResolverNull的實現(xiàn)(位于net/proxy/proxy_service.cc ):

    // Proxy resolver that fails every time. class ProxyResolverNull : public ProxyResolver {public:ProxyResolverNull() {}// ProxyResolver implementation.int GetProxyForURL(const GURL& url,ProxyInfo* results,const CompletionCallback& callback,RequestHandle* request,const BoundNetLog& net_log) override {return ERR_NOT_IMPLEMENTED;}void CancelRequest(RequestHandle request) override { NOTREACHED(); }LoadState GetLoadState(RequestHandle request) const override {NOTREACHED();return LOAD_STATE_IDLE;}}; . . . . . . class ProxyResolverFactoryForNullResolver : public ProxyResolverFactory {public:ProxyResolverFactoryForNullResolver() : ProxyResolverFactory(false) {}// ProxyResolverFactory overrides.int CreateProxyResolver(const scoped_refptr<ProxyResolverScriptData>& pac_script,std::unique_ptr<ProxyResolver>* resolver,const net::CompletionCallback& callback,std::unique_ptr<Request>* request) override {resolver->reset(new ProxyResolverNull());return OK;}private:DISALLOW_COPY_AND_ASSIGN(ProxyResolverFactoryForNullResolver); };

    由此,可以認為在Android平臺是沒有 ProxyResolver 后端的,也就是代理解析,基本上只依賴系統(tǒng)的靜態(tài)配置信息。

    ProxyService的初始化

    在 ProxyService 創(chuàng)建的時候,會做一些初始化:

    ProxyService::ProxyService(std::unique_ptr<ProxyConfigService> config_service,std::unique_ptr<ProxyResolverFactory> resolver_factory,NetLog* net_log): resolver_factory_(std::move(resolver_factory)),next_config_id_(1),current_state_(STATE_NONE),net_log_(net_log),stall_proxy_auto_config_delay_(TimeDelta::FromMilliseconds(kDelayAfterNetworkChangesMs)),quick_check_enabled_(true),sanitize_url_policy_(SanitizeUrlPolicy::SAFE) {NetworkChangeNotifier::AddIPAddressObserver(this);NetworkChangeNotifier::AddDNSObserver(this);ResetConfigService(std::move(config_service)); } . . . . . . ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {DCHECK(CalledOnValidThread());State previous_state = current_state_;permanent_error_ = OK;proxy_retry_info_.clear();script_poller_.reset();init_proxy_resolver_.reset();SuspendAllPendingRequests();resolver_.reset();config_ = ProxyConfig();if (reset_fetched_config)fetched_config_ = ProxyConfig();current_state_ = STATE_NONE;return previous_state; }void ProxyService::ResetConfigService(std::unique_ptr<ProxyConfigService> new_proxy_config_service) {DCHECK(CalledOnValidThread());State previous_state = ResetProxyConfig(true);// Release the old configuration service.if (config_service_.get())config_service_->RemoveObserver(this);// Set the new configuration service.config_service_ = std::move(new_proxy_config_service);config_service_->AddObserver(this);if (previous_state != STATE_NONE)ApplyProxyConfigIfAvailable(); }

    這里主要是將 ProxyService 對象注冊為網(wǎng)絡(luò)狀態(tài)的監(jiān)聽者,以監(jiān)聽IP地址和 DNS 的改變,并注冊為 ProxyConfigService 的監(jiān)聽者以監(jiān)聽。由于創(chuàng)建初始,previous_state 為 STATE_NONE,因而并不會做更多別的事情。

    ProxyConfigService的初始化

    ProxyConfigService 是Android平臺中 ProxyService 獲取代理配置信息的關(guān)鍵,回頭再來看 ProxyConfigService 的創(chuàng)建及初始化過程。如我們前面看到的,創(chuàng)建對象的位置在CronetURLRequestContextAdapter::InitRequestContextOnMainThread()。具體的過程( 位于net/proxy/proxy_config_service_android.cc )如下:

    ProxyConfigServiceAndroid::ProxyConfigServiceAndroid(const scoped_refptr<base::SequencedTaskRunner>& network_task_runner,const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner): delegate_(new Delegate(network_task_runner, jni_task_runner, base::Bind(&GetJavaProperty))) {delegate_->SetupJNI();delegate_->FetchInitialConfig(); }

    在這里主要是創(chuàng)建 ProxyConfigServiceAndroid::Delegate,并做初始化。初始化主要包括 SetupJNI() 和 FetchInitialConfig(),其中 SetupJNI() 是這樣的:

    class JNIDelegateImpl : public ProxyConfigServiceAndroid::JNIDelegate {public:explicit JNIDelegateImpl(Delegate* delegate) : delegate_(delegate) {} . . . . . . class ProxyConfigServiceAndroid::Delegate: public base::RefCountedThreadSafe<Delegate> {public:Delegate(const scoped_refptr<base::SequencedTaskRunner>& network_task_runner,const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner,const GetPropertyCallback& get_property_callback): jni_delegate_(this),network_task_runner_(network_task_runner),jni_task_runner_(jni_task_runner),get_property_callback_(get_property_callback),exclude_pac_url_(false) {}void SetupJNI() {DCHECK(OnJNIThread());JNIEnv* env = AttachCurrentThread();if (java_proxy_change_listener_.is_null()) {VLOG(1) << "ProxyConfigServiceAndroid::Delegate SetupJNI, try to create java_proxy_change_listener_ object";java_proxy_change_listener_.Reset(Java_ProxyChangeListener_create(env, base::android::GetApplicationContext()));CHECK(!java_proxy_change_listener_.is_null());}Java_ProxyChangeListener_start(env,java_proxy_change_listener_.obj(),reinterpret_cast<intptr_t>(&jni_delegate_));}

    可以看到,它主要是創(chuàng)建了一個類型為org.chromium.net.ProxyChangeListener 的Java對象,并調(diào)用了該對象的 start(long nativePtr) 方法( 位于net/android/java/src/org/chromium/net/ProxyChangeListener.java )。來看這個Java類的實現(xiàn):

    private ProxyChangeListener(Context context) {mContext = context;} . . . . . .@CalledByNativepublic static ProxyChangeListener create(Context context) {return new ProxyChangeListener(context);} . . . . . .@CalledByNativepublic void start(long nativePtr) {assert mNativePtr == 0;mNativePtr = nativePtr;registerReceiver();} . . . . . .private void registerReceiver() {if (mProxyReceiver != null) {return;}IntentFilter filter = new IntentFilter();filter.addAction(Proxy.PROXY_CHANGE_ACTION);mProxyReceiver = new ProxyReceiver();mContext.getApplicationContext().registerReceiver(mProxyReceiver, filter);}

    可以看到,這里主要是注冊了一個監(jiān)聽 Action 為 Proxy.PROXY_CHANGE_ACTION 的 BroadcastReceiver。再來看 FetchInitialConfig():

    // Returns whether the provided string was successfully converted to a port. bool ConvertStringToPort(const std::string& port, int* output) {url::Component component(0, port.size());int result = url::ParsePort(port.c_str(), component);if (result == url::PORT_INVALID || result == url::PORT_UNSPECIFIED)return false;*output = result;return true; }ProxyServer ConstructProxyServer(ProxyServer::Scheme scheme,const std::string& proxy_host,const std::string& proxy_port) {DCHECK(!proxy_host.empty());int port_as_int = 0;if (proxy_port.empty())port_as_int = ProxyServer::GetDefaultPortForScheme(scheme);else if (!ConvertStringToPort(proxy_port, &port_as_int))return ProxyServer();DCHECK(port_as_int > 0);return ProxyServer(scheme, HostPortPair(proxy_host, static_cast<uint16_t>(port_as_int))); }ProxyServer LookupProxy(const std::string& prefix,const GetPropertyCallback& get_property,ProxyServer::Scheme scheme) {DCHECK(!prefix.empty());std::string proxy_host = get_property.Run(prefix + ".proxyHost");if (!proxy_host.empty()) {std::string proxy_port = get_property.Run(prefix + ".proxyPort");return ConstructProxyServer(scheme, proxy_host, proxy_port);}// Fall back to default proxy, if any.proxy_host = get_property.Run("proxyHost");if (!proxy_host.empty()) {std::string proxy_port = get_property.Run("proxyPort");return ConstructProxyServer(scheme, proxy_host, proxy_port);}return ProxyServer(); }ProxyServer LookupSocksProxy(const GetPropertyCallback& get_property) {std::string proxy_host = get_property.Run("socksProxyHost");if (!proxy_host.empty()) {std::string proxy_port = get_property.Run("socksProxyPort");return ConstructProxyServer(ProxyServer::SCHEME_SOCKS5, proxy_host,proxy_port);}return ProxyServer(); }void AddBypassRules(const std::string& scheme,const GetPropertyCallback& get_property,ProxyBypassRules* bypass_rules) {// The format of a hostname pattern is a list of hostnames that are separated// by | and that use * as a wildcard. For example, setting the// http.nonProxyHosts property to *.android.com|*.kernel.org will cause// requests to http://developer.android.com to be made without a proxy.std::string non_proxy_hosts =get_property.Run(scheme + ".nonProxyHosts");if (non_proxy_hosts.empty())return;base::StringTokenizer tokenizer(non_proxy_hosts, "|");while (tokenizer.GetNext()) {std::string token = tokenizer.token();std::string pattern;base::TrimWhitespaceASCII(token, base::TRIM_ALL, &pattern);if (pattern.empty())continue;// '?' is not one of the specified pattern characters above.DCHECK_EQ(std::string::npos, pattern.find('?'));bypass_rules->AddRuleForHostname(scheme, pattern, -1);} }// Returns true if a valid proxy was found. bool GetProxyRules(const GetPropertyCallback& get_property,ProxyConfig::ProxyRules* rules) {// See libcore/luni/src/main/java/java/net/ProxySelectorImpl.java for the// mostly equivalent Android implementation. There is one intentional// difference: by default Chromium uses the HTTP port (80) for HTTPS// connections via proxy. This default is identical on other platforms.// On the opposite, Java spec suggests to use HTTPS port (443) by default (the// default value of https.proxyPort).rules->type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;rules->proxies_for_http.SetSingleProxyServer(LookupProxy("http", get_property, ProxyServer::SCHEME_HTTP));rules->proxies_for_https.SetSingleProxyServer(LookupProxy("https", get_property, ProxyServer::SCHEME_HTTP));rules->proxies_for_ftp.SetSingleProxyServer(LookupProxy("ftp", get_property, ProxyServer::SCHEME_HTTP));rules->fallback_proxies.SetSingleProxyServer(LookupSocksProxy(get_property));rules->bypass_rules.Clear();AddBypassRules("ftp", get_property, &rules->bypass_rules);AddBypassRules("http", get_property, &rules->bypass_rules);AddBypassRules("https", get_property, &rules->bypass_rules);// We know a proxy was found if not all of the proxy lists are empty.return !(rules->proxies_for_http.IsEmpty() &&rules->proxies_for_https.IsEmpty() &&rules->proxies_for_ftp.IsEmpty() &&rules->fallback_proxies.IsEmpty()); };void GetLatestProxyConfigInternal(const GetPropertyCallback& get_property,ProxyConfig* config) {if (!GetProxyRules(get_property, &config->proxy_rules()))*config = ProxyConfig::CreateDirect(); }std::string GetJavaProperty(const std::string& property) {// Use Java System.getProperty to get configuration information.// TODO(pliard): Conversion to/from UTF8 ok here?JNIEnv* env = AttachCurrentThread();ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(env, property);ScopedJavaLocalRef<jstring> result =Java_ProxyChangeListener_getProperty(env, str.obj());return result.is_null() ?std::string() : ConvertJavaStringToUTF8(env, result.obj()); } . . . . . .void FetchInitialConfig() {DCHECK(OnJNIThread());ProxyConfig proxy_config;GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);network_task_runner_->PostTask(FROM_HERE,base::Bind(&Delegate::SetNewConfigOnNetworkThread, this, proxy_config));} . . . . . .// Called on the network thread.void SetNewConfigOnNetworkThread(const ProxyConfig& proxy_config) {DCHECK(OnNetworkThread());proxy_config_ = proxy_config;FOR_EACH_OBSERVER(Observer, observers_,OnProxyConfigChanged(proxy_config,ProxyConfigService::CONFIG_VALID));}

    可以看到,這里做了兩件事,一是獲取系統(tǒng)的代理配置信息,方法主要還是通過讀取系統(tǒng)屬性完成;二是通知監(jiān)聽者,這主要是ProxyService。

    對于 Action 為 Proxy.PROXY_CHANGE_ACTION 的 BroadcastReceiver,是在注冊完成之后幾乎立即就會得到通知的。ProxyReceiver的實現(xiàn)如下:

    private class ProxyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {proxySettingsChanged(extractNewProxy(intent));}}// Extract a ProxyConfig object from the supplied Intent's extra data// bundle. The android.net.ProxyProperties class is not exported from// the Android SDK, so we have to use reflection to get at it and invoke// methods on it. If we fail, return an empty proxy config (meaning// 'direct').// TODO(sgurun): once android.net.ProxyInfo is public, rewrite this.private ProxyConfig extractNewProxy(Intent intent) {try {final String getHostName = "getHost";final String getPortName = "getPort";final String getPacFileUrl = "getPacFileUrl";final String getExclusionList = "getExclusionList";String className;String proxyInfo;if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {className = "android.net.ProxyProperties";proxyInfo = "proxy";} else {className = "android.net.ProxyInfo";proxyInfo = "android.intent.extra.PROXY_INFO";}Object props = intent.getExtras().get(proxyInfo);if (props == null) {return null;}Class<?> cls = Class.forName(className);Method getHostMethod = cls.getDeclaredMethod(getHostName);Method getPortMethod = cls.getDeclaredMethod(getPortName);Method getExclusionListMethod = cls.getDeclaredMethod(getExclusionList);String host = (String) getHostMethod.invoke(props);int port = (Integer) getPortMethod.invoke(props);String[] exclusionList;if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {String s = (String) getExclusionListMethod.invoke(props);exclusionList = s.split(",");} else {exclusionList = (String[]) getExclusionListMethod.invoke(props);}// TODO(xunjieli): rewrite this once the API is public.if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT&& Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {Method getPacFileUrlMethod = cls.getDeclaredMethod(getPacFileUrl);String pacFileUrl = (String) getPacFileUrlMethod.invoke(props);if (!TextUtils.isEmpty(pacFileUrl)) {return new ProxyConfig(host, port, pacFileUrl, exclusionList);}} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {Method getPacFileUrlMethod = cls.getDeclaredMethod(getPacFileUrl);Uri pacFileUrl = (Uri) getPacFileUrlMethod.invoke(props);if (!Uri.EMPTY.equals(pacFileUrl)) {return new ProxyConfig(host, port, pacFileUrl.toString(), exclusionList);}}return new ProxyConfig(host, port, null, exclusionList);} catch (ClassNotFoundException ex) {Log.e(TAG, "Using no proxy configuration due to exception:" + ex);return null;} catch (NoSuchMethodException ex) {Log.e(TAG, "Using no proxy configuration due to exception:" + ex);return null;} catch (IllegalAccessException ex) {Log.e(TAG, "Using no proxy configuration due to exception:" + ex);return null;} catch (InvocationTargetException ex) {Log.e(TAG, "Using no proxy configuration due to exception:" + ex);return null;} catch (NullPointerException ex) {Log.e(TAG, "Using no proxy configuration due to exception:" + ex);return null;}}}private void proxySettingsChanged(ProxyConfig cfg) {if (!sEnabled) {return;}if (mDelegate != null) {mDelegate.proxySettingsChanged();}if (mNativePtr == 0) {return;}// Note that this code currently runs on a MESSAGE_LOOP_UI thread, but// the C++ code must run the callbacks on the network thread.if (cfg != null) {nativeProxySettingsChangedTo(mNativePtr, cfg.mHost, cfg.mPort, cfg.mPacUrl,cfg.mExclusionList);} else {nativeProxySettingsChanged(mNativePtr);}}

    這個Receiver在收到通知后,會將代理信息傳遞到C/C++層。最終調(diào)用ProxyConfigServiceAndroid::Delegate::JNIDelegateImpl:

    // ProxyConfigServiceAndroid::JNIDelegate overrides.void ProxySettingsChangedTo(JNIEnv* env,const JavaParamRef<jobject>& jself,const JavaParamRef<jstring>& jhost,jint jport,const JavaParamRef<jstring>& jpac_url,const JavaParamRef<jobjectArray>& jexclusion_list) override {std::string host = ConvertJavaStringToUTF8(env, jhost);std::string pac_url;if (jpac_url)ConvertJavaStringToUTF8(env, jpac_url, &pac_url);std::vector<std::string> exclusion_list;base::android::AppendJavaStringArrayToStringVector(env, jexclusion_list, &exclusion_list);delegate_->ProxySettingsChangedTo(host, jport, pac_url, exclusion_list);}void ProxySettingsChanged(JNIEnv* env,const JavaParamRef<jobject>& self) override {delegate_->ProxySettingsChanged();}private:Delegate* const delegate_;};

    繼而調(diào)用 ProxyConfigServiceAndroid::Delegate 的相應(yīng)方法:

    void CreateStaticProxyConfig(const std::string& host,int port,const std::string& pac_url,const std::vector<std::string>& exclusion_list,ProxyConfig* config) {if (!pac_url.empty()) {config->set_pac_url(GURL(pac_url));config->set_pac_mandatory(false);} else if (port != 0) {std::string rules = base::StringPrintf("%s:%d", host.c_str(), port);config->proxy_rules().ParseFromString(rules);config->proxy_rules().bypass_rules.Clear();std::vector<std::string>::const_iterator it;for (it = exclusion_list.begin(); it != exclusion_list.end(); ++it) {std::string pattern;base::TrimWhitespaceASCII(*it, base::TRIM_ALL, &pattern);if (pattern.empty())continue;config->proxy_rules().bypass_rules.AddRuleForHostname("", pattern, -1);}} else {*config = ProxyConfig::CreateDirect();} } . . . . . .// Called on the JNI thread.void ProxySettingsChanged() {DCHECK(OnJNIThread());ProxyConfig proxy_config;GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);network_task_runner_->PostTask(FROM_HERE,base::Bind(&Delegate::SetNewConfigOnNetworkThread, this, proxy_config));}// Called on the JNI thread.void ProxySettingsChangedTo(const std::string& host,int port,const std::string& pac_url,const std::vector<std::string>& exclusion_list) {DCHECK(OnJNIThread());ProxyConfig proxy_config;if (exclude_pac_url_) {CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config);} else {CreateStaticProxyConfig(host, port, pac_url, exclusion_list,&proxy_config);}network_task_runner_->PostTask(FROM_HERE,base::Bind(&Delegate::SetNewConfigOnNetworkThread, this, proxy_config));}

    ProxySettingsChanged()如同 FetchInitialConfig() 一樣,是從system property中獲取代理配置信息,并通知監(jiān)聽者。而 ProxySettingsChangedTo() 則是以傳入的代理配置信息構(gòu)造配置,并通知監(jiān)聽者。

    可見,BroadcastReceiver 通知時的這次配置信息更新會沖掉最初通過 FetchInitialConfig() 獲取的那些。

    總結(jié)一下,在Android中,chromium net獲取代理配置信息的方法是:

  • 在 ProxyConfigServiceAndroid 創(chuàng)建過程中,從system property中讀取代理設(shè)置信息,同時注冊BroadcastReceiver以監(jiān)聽系統(tǒng)代理配置的改變。
  • 在收到系統(tǒng)廣播消息的通知時,若廣播中包含詳細的代理配置信息,則以這些信息更新Chromium net的代理設(shè)置;否則,再次讀取system property獲取代理配置信息。
  • 代理解析

    ProxyConfigService 在代理配置發(fā)生改變時,會將新的代理配置通知給ProxyService:

    void ProxyService::SetReady() {DCHECK(!init_proxy_resolver_.get());current_state_ = STATE_READY;// Make a copy in case |this| is deleted during the synchronous completion// of one of the requests. If |this| is deleted then all of the PacRequest// instances will be Cancel()-ed.PendingRequests pending_copy = pending_requests_;for (PendingRequests::iterator it = pending_copy.begin();it != pending_copy.end();++it) {PacRequest* req = it->get();if (!req->is_started() && !req->was_cancelled()) {req->net_log()->EndEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);// Note that we re-check for synchronous completion, in case we are// no longer using a ProxyResolver (can happen if we fell-back to manual).req->StartAndCompleteCheckingForSynchronous();}} } . . . . . . void ProxyService::OnProxyConfigChanged(const ProxyConfig& config,ProxyConfigService::ConfigAvailability availability) {// Retrieve the current proxy configuration from the ProxyConfigService.// If a configuration is not available yet, we will get called back later// by our ProxyConfigService::Observer once it changes.ProxyConfig effective_config;switch (availability) {case ProxyConfigService::CONFIG_PENDING:// ProxyConfigService implementors should never pass CONFIG_PENDING.NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";return;case ProxyConfigService::CONFIG_VALID:effective_config = config;break;case ProxyConfigService::CONFIG_UNSET:effective_config = ProxyConfig::CreateDirect();break;}// Emit the proxy settings change to the NetLog stream.if (net_log_) {net_log_->AddGlobalEntry(NetLog::TYPE_PROXY_CONFIG_CHANGED,base::Bind(&NetLogProxyConfigChangedCallback,&fetched_config_, &effective_config));}// Set the new configuration as the most recently fetched one.fetched_config_ = effective_config;fetched_config_.set_id(1); // Needed for a later DCHECK of is_valid().InitializeUsingLastFetchedConfig(); }void ProxyService::InitializeUsingLastFetchedConfig() {ResetProxyConfig(false);DCHECK(fetched_config_.is_valid());// Increment the ID to reflect that the config has changed.fetched_config_.set_id(next_config_id_++);if (!fetched_config_.HasAutomaticSettings()) {config_ = fetched_config_;SetReady();return;}// Start downloading + testing the PAC scripts for this new configuration.current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;// If we changed networks recently, we should delay running proxy auto-config.TimeDelta wait_delay =stall_proxy_autoconfig_until_ - TimeTicks::Now();init_proxy_resolver_.reset(new InitProxyResolver());init_proxy_resolver_->set_quick_check_enabled(quick_check_enabled_);int rv = init_proxy_resolver_->Start(&resolver_, resolver_factory_.get(), proxy_script_fetcher_.get(),dhcp_proxy_script_fetcher_.get(), net_log_, fetched_config_, wait_delay,base::Bind(&ProxyService::OnInitProxyResolverComplete,base::Unretained(this)));if (rv != ERR_IO_PENDING)OnInitProxyResolverComplete(rv); }

    在這里主要是將新的代理配置信息保存在 fetched_config_ 中,繼而將配置保存在 config_ 中,并設(shè)置狀態(tài)標記 current_state_ 為 ready。

    HttpStreamFactoryImpl::Job::DoResolveProxy() 通過 ProxyService 的 ResolveProxy() 來為特定的URL找到合適的代理服務(wù)器:

    int ProxyService::ResolveProxy(const GURL& raw_url,const std::string& method,ProxyInfo* result,const CompletionCallback& callback,PacRequest** pac_request,ProxyDelegate* proxy_delegate,const BoundNetLog& net_log) {DCHECK(!callback.is_null());return ResolveProxyHelper(raw_url, method, result, callback, pac_request,proxy_delegate, net_log); }int ProxyService::ResolveProxyHelper(const GURL& raw_url,const std::string& method,ProxyInfo* result,const CompletionCallback& callback,PacRequest** pac_request,ProxyDelegate* proxy_delegate,const BoundNetLog& net_log) {DCHECK(CalledOnValidThread());net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE);// Notify our polling-based dependencies that a resolve is taking place.// This way they can schedule their polls in response to network activity.config_service_->OnLazyPoll();if (script_poller_.get())script_poller_->OnLazyPoll();if (current_state_ == STATE_NONE)ApplyProxyConfigIfAvailable();// Sanitize the URL before passing it on to the proxy resolver (i.e. PAC// script). The goal is to remove sensitive data (like embedded user names// and password), and local data (i.e. reference fragment) which does not need// to be disclosed to the resolver.GURL url = SanitizeUrl(raw_url, sanitize_url_policy_);// Check if the request can be completed right away. (This is the case when// using a direct connection for example).int rv = TryToCompleteSynchronously(url, proxy_delegate, result);if (rv != ERR_IO_PENDING) {rv = DidFinishResolvingProxy(url, method, proxy_delegate, result, rv, net_log,callback.is_null() ? TimeTicks() : TimeTicks::Now(), false);return rv;}if (callback.is_null())return ERR_IO_PENDING;scoped_refptr<PacRequest> req(new PacRequest(this, url, method, proxy_delegate, result, callback, net_log));if (current_state_ == STATE_READY) {// Start the resolve request.rv = req->Start();if (rv != ERR_IO_PENDING)return req->QueryDidComplete(rv);} else {req->net_log()->BeginEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);}DCHECK_EQ(ERR_IO_PENDING, rv);DCHECK(!ContainsPendingRequest(req.get()));pending_requests_.insert(req);// Completion will be notified through |callback|, unless the caller cancels// the request using |pac_request|.if (pac_request)*pac_request = req.get();return rv; // ERR_IO_PENDING } . . . . . . int ProxyService::TryToCompleteSynchronously(const GURL& url,ProxyDelegate* proxy_delegate,ProxyInfo* result) {DCHECK_NE(STATE_NONE, current_state_);if (current_state_ != STATE_READY)return ERR_IO_PENDING; // Still initializing.DCHECK_NE(config_.id(), ProxyConfig::kInvalidConfigID);// If it was impossible to fetch or parse the PAC script, we cannot complete// the request here and bail out.if (permanent_error_ != OK)return permanent_error_;if (config_.HasAutomaticSettings())return ERR_IO_PENDING; // Must submit the request to the proxy resolver.// Use the manual proxy settings.config_.proxy_rules().Apply(url, result);result->config_source_ = config_.source();result->config_id_ = config_.id();return OK; }

    這個過程應(yīng)用代理規(guī)則,選擇適當?shù)拇矸?wù)器給調(diào)用者。

    Done。

    參考資料

    Proxy server
    教你在Android手機上使用全局代理

    總結(jié)

    以上是生活随笔為你收集整理的Android平台Chromium net中的代理配置信息获取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    国产一二区免费视频 | 国产成人精品一区在线 | 亚洲激情综合 | 国产男女无遮挡猛进猛出在线观看 | 麻花豆传媒mv在线观看网站 | 美女网站视频免费都是黄 | 黄色官网在线观看 | av在线一级 | 天天干,天天操 | 欧美一级黄色片 | 亚洲激情 | 麻豆免费观看视频 | 亚洲做受高潮欧美裸体 | 免费在线一区二区 | 在线午夜 | 综合激情网... | 亚洲日本激情 | 欧美一级免费高清 | 国产精品尤物 | www.天天操.com| 97成人在线观看 | 日韩成人免费在线 | 亚洲精品乱码白浆高清久久久久久 | 日韩一区在线免费观看 | 国产精品久久久久久久久久 | 99综合影院在线 | 偷拍区另类综合在线 | 国产亚洲精品福利 | 亚洲精品999 | 亚洲三级视频 | 午夜在线免费视频 | 午夜视频在线观看一区二区 | 国产精品ⅴa有声小说 | 激情综合中文娱乐网 | 日韩精品在线视频 | 成人作爱视频 | 亚洲欧美日韩一二三区 | 国产欧美中文字幕 | 欧美日韩性生活 | 天天操天天射天天舔 | 国产精品日韩高清 | 91网站在线视频 | 国产亚洲精品久久久久久无几年桃 | 成年人在线看视频 | 黄色片免费在线 | 欧美一级性视频 | 国产成人久久av免费高清密臂 | 99久久精品免费看国产免费软件 | 欧美久草网| 超级碰99| 色黄久久久久久 | 欧美精品免费在线观看 | 97电影院在线观看 | 午夜精品电影一区二区在线 | 成人香蕉视频 | 97久久久免费福利网址 | 欧美视频日韩 | 久久久久久久久久久国产精品 | 99免费在线| 波多野结衣视频一区二区三区 | 美女久久 | 免费视频91| 激情久久伊人 | 一级做a爱片性色毛片www | 国产一区二区高清 | 久久综合狠狠狠色97 | 在线观看亚洲电影 | 日韩mv欧美mv国产精品 | 亚洲精品国产精品乱码不99热 | 人人射人人澡 | 97超碰人人模人人人爽人人爱 | 91麻豆视频 | 日日夜夜天天综合 | 久久免费视频一区 | 天天色天天干天天色 | 中文字幕在线看视频 | 色综合久久久久网 | 欧美一区二区三区免费观看 | 天堂中文在线视频 | 欧美淫aaa免费观看 日韩激情免费视频 | 欧美看片| 亚洲最新精品 | 91av中文字幕| 99国产精品久久久久久久久久 | 中文字幕av免费 | 亚洲国产日韩精品 | 久久a级片| 在线观看视频免费大全 | 日日干美女 | 国产在线美女 | 精品欧美一区二区在线观看 | 一区二区三区日韩视频在线观看 | 91免费高清在线观看 | 午夜精品麻豆 | 狠狠色丁香婷综合久久 | 狠狠狠狠狠狠狠干 | 国产成人精品综合 | 国内精品久久久久久久久久 | 91丨porny丨九色 | 日本久久中文字幕 | 国产在线2020| 黄色免费视频在线观看 | 99久久久久成人国产免费 | av在线专区 | 午夜视频免费播放 | 日日爽天天 | 欧美一级日韩三级 | 色综合久久久久久久久五月 | 久久爱992xxoo | 九九九九热精品免费视频点播观看 | 精品一二区 | 中文字幕资源网 国产 | 国产精品大尺度 | 九色视频网 | 国产午夜三级 | 天天干天天做 | 国产在线不卡视频 | 91视频啊啊啊 | 亚洲精品毛片一级91精品 | 999久久久欧美日韩黑人 | 中文字幕亚洲欧美日韩2019 | www国产一区 | 久久久久久久免费观看 | 亚洲国产成人在线播放 | 国产一区二区高清不卡 | 国产va在线 | 99在线免费视频观看 | 日韩三级.com | 九九热在线观看视频 | 黄色的视频网站 | 亚洲成人资源网 | 超碰com| 在线一级片 | 欧美精品久久久久久久亚洲调教 | 黄a网站 | 欧美综合国产 | 新av在线 | 久久理论电影网 | 96香蕉视频| 国产精品久久久久久久免费 | 国产精品地址 | 国产在线播放一区二区 | 精品在线视频播放 | 免费高清在线观看电视网站 | 国产黄色看片 | 国产视频久久久 | 六月丁香激情综合色啪小说 | 91av免费看 | 国产在线欧美在线 | 国产色拍拍拍拍在线精品 | 国产视频一区二区在线 | 久草在线久| 日韩在线免费电影 | 日日弄天天弄美女bbbb | 国产一级在线视频 | 成人在线中文字幕 | 国产在线更新 | 国产精品女 | 国产精品女人久久久 | 黄色毛片视频免费观看中文 | 日韩在线看片 | 精品久久久久久久久中文字幕 | 日本最新一区二区三区 | 91av在线国产 | 国产成人久久久久 | 超碰人人舔 | 青草视频在线 | 日本精品xxxx | 国产一级二级在线观看 | 欧美三级在线播放 | 国产精品6 | 日本公妇色中文字幕 | 中文字幕在线观看视频免费 | 97国产精品亚洲精品 | 97精品国产91久久久久久 | 免费国产黄线在线观看视频 | 亚洲色图av | 成人一区二区在线观看 | 91亚·色 | 久久精品99国产国产精 | 91精品一区二区在线观看 | 国产精品免费高清 | 天堂在线视频免费观看 | 日韩免费观看一区二区 | 日日夜夜精品视频 | 国产不卡一二三区 | 成年人在线播放视频 | 国产尤物视频在线 | 国产91亚洲 | 丁香激情婷婷 | 日韩电影中文 | 免费视频黄 | 一级片在线 | 成人av片免费观看app下载 | 最近免费中文字幕mv在线视频3 | 欧美精品免费视频 | 国产亚洲综合性久久久影院 | 久草在线资源网 | 午夜精品久久久久久久99婷婷 | 在线视频久 | 中文字幕 国产专区 | 91av免费在线观看 | 91网免费看 | 婷五月天激情 | 国产精品美女999 | 中文字幕在线视频第一页 | jizzjizzjizz亚洲 | 免费激情网| 成人在线免费看视频 | 天天鲁一鲁摸一摸爽一爽 | 国产欧美综合视频 | 在线观看黄色 | 久久色视频 | 国产精品视频内 | 69国产精品视频免费观看 | 涩涩网站在线播放 | 久久大片| 欧美伦理一区 | 国产日韩精品在线观看 | 国产欧美最新羞羞视频在线观看 | 日韩精品一区在线播放 | 91久久国产露脸精品国产闺蜜 | 久久视频在线 | 天天色影院 | 国产在线精品视频 | 91精品爽啪蜜夜国产在线播放 | 欧美黑人xxxx猛性大交 | 精品91在线 | 91高清不卡 | 91视频免费国产 | 91一区二区三区久久久久国产乱 | 69精品视频 | 91av网站在线观看 | 欧美另类高潮 | 精品久久久国产 | 国产玖玖在线 | 精品中文字幕在线 | 午夜精品久久久久99热app | 91精品国产91久久久久福利 | 久久视频这里有久久精品视频11 | 久久免费看a级毛毛片 | 亚洲天堂自拍视频 | 黄色在线成人 | 日韩国产精品久久 | 欧美成人性网 | 国产精品久久一区二区三区不卡 | 亚洲国产免费看 | 精品国产1区2区 | 国产片免费在线观看视频 | 久久天天拍 | 欧美性做爰猛烈叫床潮 | 日韩电影在线观看一区二区 | 黄色看片 | 午夜在线国产 | 伊人小视频 | 少妇精品久久久一区二区免费 | 国产精品国内免费一区二区三区 | av综合网址| 日本精品视频免费观看 | a级成人毛片 | 韩国av一区二区三区在线观看 | 国产亚洲小视频 | 黄色片网站免费 | 美女视频又黄又免费 | 国产主播99 | 在线激情小视频 | 国产精品久久久久一区二区 | 综合激情 | 绯色av一区 | 天天插夜夜操 | 九九免费观看全部免费视频 | 国产精品毛片久久久 | 久久爽久久爽久久av东京爽 | 久久精品一区二区三区四区 | 日韩在线免费电影 | 亚洲国产高清在线 | 国产亚洲精品美女 | 日韩精品一区二区在线观看视频 | 日本性生活免费看 | 久久精品免费 | 波多野结衣视频一区二区 | 九色精品免费永久在线 | 丁五月婷婷 | 国产黄色精品在线 | 91亚洲夫妻| 精品99久久久久久 | 国产一级片不卡 | 波多野结衣精品 | 精品久久国产精品 | www激情网| 三级黄色在线 | 毛片永久免费 | 国产亚洲字幕 | 丁香五婷 | 99久久婷婷国产一区二区三区 | 亚洲精品乱码久久久久久按摩 | 日韩在线免费观看视频 | 亚洲综合黄色 | 成人免费在线观看电影 | 日韩激情一二三区 | 天天爱天天 | 最近高清中文字幕在线国语5 | 国产精品白丝jk白祙 | 亚洲黄色av一区 | 99精品国产一区二区三区麻豆 | 亚洲国产成人精品电影在线观看 | 欧美精品久久久久久久久久白贞 | 国内精品视频久久 | 国产成人精品一区二区三区网站观看 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 国产成人精品午夜在线播放 | 美女一级毛片视频 | 日日碰狠狠躁久久躁综合网 | av网站地址 | 免费av高清 | 在线综合色 | 91福利影院在线观看 | 中文av在线免费观看 | 日韩高清免费在线观看 | 欧美日韩视频免费看 | 看v片 | 久久精精品 | 九九99| 国产资源在线播放 | www日韩精品 | 激情电影影院 | 国内精品小视频 | 亚洲综合成人婷婷小说 | 国产人成在线观看 | 黄色的视频 | 青青久草在线 | 二区三区在线 | 国产高清在线 | 日韩女同一区二区三区在线观看 | 亚洲精品tv | 精品国自产在线观看 | 成年人免费看 | 久久久久久高潮国产精品视 | 91成人区 | 涩涩网站免费 | 伊人久在线 | 成人免费中文字幕 | 国产精品成人一区二区三区吃奶 | 美女免费网视频 | 久久中文字幕导航 | 亚洲天堂毛片 | 激情综合网在线观看 | 亚洲精品xxxx | 亚洲精品国产综合久久 | 91伊人久久大香线蕉蜜芽人口 | 色综合天天色 | 日本爱爱免费 | 日韩电影中文 | 丁香婷婷深情五月亚洲 | 亚洲天堂毛片 | 中文字幕日本在线观看 | 国产精品婷婷午夜在线观看 | 国产精品免费久久久久久久久久中文 | 久草在线免费看视频 | 色 免费观看 | 久草视频中文在线 | 国产v在线播放 | 日本中文字幕视频 | 日韩中文字幕电影 | 国产成人精品电影久久久 | 中文字幕中文字幕在线中文字幕三区 | 日日爽夜夜操 | 成人毛片在线视频 | 色av资源网 | 国产一区二区电影在线观看 | 国产高清精品在线 | 亚洲欧洲精品视频 | 97超碰在线人人 | 久久久午夜剧场 | 国产亚洲一区二区在线观看 | 国产老太婆免费交性大片 | 国产成人a v电影 | 大片网站久久 | 九九综合九九 | 天天综合色天天综合 | 久久久999| av色一区 | 免费在线观看日韩欧美 | 天天操夜夜干 | 色网站中文字幕 | 中文字幕av最新 | 综合色站 | 狠狠干激情 | 亚洲一区视频免费观看 | 草久久精品 | 精品久久久久国产 | 日本九九视频 | 久久色中文字幕 | 欧日韩在线视频 | 国产精品一区二区三区在线看 | 操操碰 | 亚洲视频第一页 | 午夜av大片| 久久久综合九色合综国产精品 | 91在线入口 | 国产理论一区二区三区 | 黄色av网站在线免费观看 | 久热香蕉视频 | 亚州精品成人 | 国产日韩在线一区 | 国产精品久久久久久久久婷婷 | 国产高清免费 | 天天伊人狠狠 | 国产又粗又猛又色又黄视频 | 国产精品欧美久久久久三级 | 久久精品一二三区 | 在线观看www91| 亚洲91av| 亚洲国产高清在线观看视频 | 免费国产亚洲视频 | 中文区中文字幕免费看 | 人人爽人人做 | 亚洲精品高清一区二区三区四区 | 亚洲精品乱码久久久久久 | 在线观看日韩免费视频 | 国产亚洲精品综合一区91 | 91传媒在线播放 | av久久久久久| 99精品视频一区二区 | 色视频在线免费 | 色吧av色av | 91亚洲精品视频 | 综合色站导航 | 久久爱资源网 | 天天干天天干天天干天天干天天干天天干 | 黄色字幕网| 日韩精品免费一区二区在线观看 | 日韩午夜大片 | 在线观看不卡视频 | 探花视频在线观看 | 日韩黄色在线电影 | av成人免费在线看 | 国产一区二区在线视频观看 | 成人免费电影 | 久久专区| 国产香蕉久久 | 成人av资源在线 | 亚洲一区二区天堂 | 成人在线观看av | 国产午夜三级一区二区三 | 奇米网在线观看 | 成人av免费在线播放 | 欧美日韩裸体免费视频 | 国产精品丝袜久久久久久久不卡 | 黄色av电影在线 | 亚洲精品国产综合99久久夜夜嗨 | 四虎影视精品永久在线观看 | 国产高清在线免费视频 | 亚洲欧美国产视频 | 久久国色夜色精品国产 | 久久a级片 | 精品视频免费观看 | 亚洲一区不卡视频 | 久久精品中文字幕 | 中文av日韩 | 欧美激情第八页 | 国产a精品 | 日韩xxxx视频 | 国产资源 | 91网页版免费观看 | 国产一级特黄电影 | 日日爱999| 久草在线手机观看 | 国产精品永久久久久久久www | 九九九免费视频 | 久久久久亚洲最大xxxx | 在线看不卡av| 久久激情网站 | 精品久久久久亚洲 | 视频在线播放国产 | 国产精品久久久久久久久久ktv | 91成人免费视频 | 久久久久久久久黄色 | 国产69精品久久app免费版 | 国产资源中文字幕 | 国产日韩视频在线播放 | 欧美大片www | 久久久免费观看 | 成年人视频在线 | 日韩av片在线| 国产免费久久精品 | 一区二区三区在线免费观看视频 | 国产精品网红直播 | 四虎国产精品免费 | 精品国产电影一区二区 | 成人禁用看黄a在线 | 国产综合视频在线观看 | www日韩| 国产一级片不卡 | 亚洲视频99| 色亚洲网 | 超碰日韩 | 色网站免费在线观看 | 中文字幕中文 | a天堂最新版中文在线地址 久久99久久精品国产 | 免费在线成人 | 2019精品手机国产品在线 | 美女黄网久久 | 人人添人人澡人人澡人人人爽 | 96精品视频| 久久美女电影 | 国产视频在线一区二区 | 成人精品久久 | 国产精品ⅴa有声小说 | 色婷婷视频在线观看 | 91大神在线观看视频 | 在线观看成人网 | 欧美日韩国产一二三区 | 人人澡人 | 婷婷五综合 | 中文字幕乱码一区二区 | 婷婷综合久久 | 中文在线a∨在线 | 伊人五月天综合 | 免费看的黄网站 | 成人av高清在线 | www日韩欧美 | 国产在线播放一区 | 日本一区二区三区免费观看 | 午夜精品影院 | 中文字幕一区二区三区在线视频 | 久久久网| 激情综合国产 | 欧美精品第一 | 在线播放视频一区 | 日韩av在线一区二区 | 在线小视频国产 | 久久久久久久久综合 | 久久综合精品一区 | 99久久久久久久久久 | 国产精品婷婷午夜在线观看 | 国产黄色片免费看 | 日韩电影中文字幕 | 婷婷伊人五月 | 亚洲激情在线视频 | 久久调教视频 | 免费观看xxxx9999片 | 中文国产在线观看 | 综合色婷婷 | 久久综合九色综合欧美就去吻 | 国产中文字幕在线观看 | 亚洲va综合va国产va中文 | 99热在线观看免费 | 欧美日韩一级久久久久久免费看 | 色网站视频 | 91亚洲精品国偷拍自产在线观看 | 在线影视 一区 二区 三区 | 狠狠网站 | 色无五月 | 欧美91精品国产自产 | 色综合亚洲精品激情狠狠 | av日韩在线网站 | 中文字幕日韩伦理 | 香蕉97视频观看在线观看 | 久久99网站| 久久精品区 | 免费三级黄色 | av色一区 | 久草在线久 | 大型av综合网站 | 99精品欧美一区二区三区黑人哦 | 成年人天堂com | 超碰成人网 | 夜夜爽88888免费视频4848 | 丁香婷婷综合激情五月色 | 亚洲精品乱码久久久久v最新版 | 国产在线观看h | 午夜视频色 | 最近中文字幕mv免费高清在线 | 麻豆视频www | 精品国产aⅴ一区二区三区 在线直播av | 久久精品亚洲国产 | 在线观看视频你懂 | 五月天婷婷视频 | 久久国产综合视频 | 精品一区二区6 | 久久不色 | 18性欧美xxxⅹ性满足 | 免费性网站| 97精品伊人| 国产精品久久人 | 亚洲激情小视频 | 国产精品久久久久久麻豆一区 | 婷婷久月| 日韩一级理论片 | 精品在线不卡 | 久久国产精品精品国产色婷婷 | 99婷婷狠狠成为人免费视频 | 日韩视频一 | 成人a毛片 | 久久国产精品99久久人人澡 | 五月婷婷毛片 | 91探花国产综合在线精品 | 看片一区二区三区 | www视频在线免费观看 | 中文字幕成人一区 | 欧洲亚洲精品 | 激情开心色 | 视频在线播放国产 | 色人久久 | av福利网址导航 | 欧美吞精| 国产在线美女 | 女人高潮特级毛片 | 在线观看一二三区 | 超碰97国产精品人人cao | av网站手机在线观看 | 日韩精品视频免费专区在线播放 | 日韩在线字幕 | 黄色大片网 | 欧美一级黄色视屏 | 国产精品久久久久久一区二区三区 | 97在线免费视频 | 9草在线| 涩涩伊人 | 极品嫩模被强到高潮呻吟91 | 日韩欧美国产视频 | 久久久影院官网 | 天天射天天艹 | 国内一区二区视频 | 亚洲午夜小视频 | 国产精品 日韩精品 | 久久精品日本啪啪涩涩 | 综合激情| 成人av电影网址 | 亚洲精选久久 | 97超碰在线播放 | 一区二区视频免费在线观看 | 精品自拍网 | 日本中文字幕在线电影 | 亚洲精品视频免费观看 | 天天色播| 亚洲综合成人专区片 | 亚洲精品一区二区三区新线路 | 国产精品a级 | 久草国产在线观看 | 天堂成人在线 | 国产不卡精品视频 | 九九九在线观看视频 | 欧洲性视频| 色婷婷久久久综合中文字幕 | 久久艹国产 | 国产精品一区二区久久久 | 久久免费观看少妇a级毛片 久久久久成人免费 | 欧美极品裸体 | 亚洲日本精品 | 成 人 免费 黄 色 视频 | 精品视频免费久久久看 | av最新资源 | 国产精品视频 | 91麻豆文化传媒在线观看 | 日日夜夜亚洲 | 日日干网 | 狠狠久久伊人 | 五月激情综合婷婷 | 亚洲免费观看在线视频 | 日本女人在线观看 | 成人免费在线观看av | 久久精品国产精品亚洲 | 91色在线观看视频 | 久久精品亚洲精品国产欧美 | 国产一线二线三线性视频 | 区一区二区三区中文字幕 | 2019中文字幕第一页 | 国产在线观看a | 国产精品成人免费一区久久羞羞 | 国产亚洲va综合人人澡精品 | 欧美日韩免费观看一区二区三区 | 久久精品资源 | 又爽又黄又无遮挡网站动态图 | 午夜av电影 | 国产亚洲欧洲 | 激情综合中文娱乐网 | 日日干天天 | 国产一区二区精品久久91 | 国产精品孕妇 | 国产三级视频在线 | 精品久久久久久久久久国产 | 天天射射天天 | 操操操夜夜操 | 中文字幕黄色av | 日韩在线一二三区 | 伊人小视频 | 亚洲欧美在线视频免费 | 色婷婷综合久久久久中文字幕1 | 黄色av一级| 国产剧情在线一区 | 日日夜夜精品视频 | 亚洲人成网站精品片在线观看 | 亚洲小视频在线观看 | 91免费日韩 | 国产精品一区二区久久 | 美女黄网站视频免费 | 日本精品久久久久 | 亚洲经典在线 | 五月婷综合 | 国产日韩欧美在线一区 | 久久女同性恋中文字幕 | 国产亚洲日 | 亚洲国产成人精品久久 | 99精彩视频| 中文字幕精品一区二区精品 | 精品国产大片 | 亚洲国产97在线精品一区 | 亚洲h在线播放在线观看h | 日日夜夜人人天天 | 久久国产成人午夜av影院宅 | 99精品久久精品一区二区 | 亚洲a色 | 午夜三级福利 | 久久经典国产视频 | 欧美日韩综合在线观看 | 精品国产中文字幕 | 欧美亚洲国产日韩 | 在线成人av | 色综合狠狠干 | 97精品久久人人爽人人爽 | 久久tv| 国产精品精品 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 亚洲黄色网络 | 99热精品国产 | 国产欧美精品一区二区三区四区 | 五月开心六月伊人色婷婷 | 国产中文视频 | 亚洲精品在线观看av | 日本韩国精品一区二区在线观看 | 免费观看成人网 | 激情网站五月天 | 爱情影院aqdy鲁丝片二区 | ,久久福利影视 | 99爱精品在线| 日韩av偷拍| 国产精品久久久久毛片大屁完整版 | 91丨九色丨91啦蝌蚪老版 | 久久国产精品一区二区三区 | 中文字幕精品视频 | 日韩欧美在线免费观看 | 色久综合 | 国产小视频91 | 成人av在线直播 | 97视频免费观看 | 在线国产91 | 亚洲精品视频在线看 | 最近久乱中文字幕 | 日韩大片免费在线观看 | 久久亚洲免费视频 | 亚洲激情小视频 | 国产91精品在线播放 | 日本性久久 | 黄色大片日本免费大片 | 久久久精品高清 | 缴情综合网五月天 | 国产手机在线观看视频 | 成人国产精品免费 | 久久亚洲综合国产精品99麻豆的功能介绍 | 亚洲视频aaa | 激情av资源 | 久久久久久久久久久久久久免费看 | 久久久久久久久久久久久国产精品 | 国产成人精品电影久久久 | 国产高清不卡 | 中文字幕精品一区二区三区电影 | 国产手机在线观看 | 精品国产大片 | 精品亚洲免费视频 | 九九视频免费在线观看 | 日韩av成人 | 国产午夜精品久久 | 国产精品一区二区免费在线观看 | 久久99精品国产一区二区三区 | 久久精品视频18 | 日韩理论电影网 | 2019中文字幕第一页 | 中文字幕久久精品一区 | 天干啦夜天干天干在线线 | 色婷婷在线视频 | 国产99久久精品 | 国产精品区二区三区日本 | 激情开心色| 久久视频这里有久久精品视频11 | 国产成人三级在线播放 | 久久夜色精品国产亚洲aⅴ 91chinesexxx | 成人在线观看你懂的 | 欧美va电影 | 美女黄久久 | 亚洲精品乱码久久久久v最新版 | 在线看片中文字幕 | 四虎在线永久免费观看 | 1024手机基地在线观看 | 黄色软件视频大全免费下载 | 亚洲精品国偷自产在线91正片 | 久久精品婷婷 | av一二三区 | 亚洲精品乱码久久久久久蜜桃欧美 | 欧美九九视频 | 久久久免费少妇 | 成人黄色电影在线 | 久久99国产精品视频 | 久久综合久久综合久久综合 | 日韩大片免费观看 | 色在线网| 黄av在线| 最新日韩在线 | 黄色a视频| 青春草免费在线视频 | 91精品久久久久久综合乱菊 | 国产成人亚洲在线观看 | 日韩在线观看高清 | 国产精品午夜在线观看 | 在线视频91 | 国产视频一二三 | 久久成人国产精品免费软件 | 久久精品一二三区白丝高潮 | 亚洲精品在线观看av | 91黄色小视频 | 成人中文字幕+乱码+中文字幕 | 日韩啪视频 | 亚州欧美视频 | 国产一区在线播放 | 天天激情站 | 黄色影院在线免费观看 | 一本一本久久a久久精品牛牛影视 | 最近更新中文字幕 | 中文字幕一区二区三区精华液 | www.com操| 操天天操| 久久亚洲区 | 欧美黄色软件 | 国产偷在线 | 亚洲欧美日韩精品一区二区 | 人人澡人人舔 | 亚洲国产美女久久久久 | 天天射天天干天天插 | 成人免费在线观看入口 | 日韩精品一卡 | 夜夜狠狠 | 国产又粗又猛又色 | 久久精品首页 | 国产手机视频在线观看 | 麻豆一精品传二传媒短视频 | 国产午夜剧场 | 久久久精品福利视频 | 亚洲欧美少妇 | 天天综合久久 | 久 久久影院 | 又爽又黄又无遮挡网站动态图 | 一区二区在线影院 | 在线观看免费版高清版 | 欧美专区国产专区 | 天天操网站 | 欧美久久精品 | 成人h视频 | 中文字幕av专区 | 亚洲国产精品视频在线观看 | 国产精品久久久久四虎 | 亚洲精品色 | 欧美精品久久久久久久久久久 | 精品国产一区二区三区在线 | 91精品人成在线观看 | 欧美激情精品久久久 | 久久视频热| 国产精品视频线看 | 欧美日韩有码 | 国产一级视屏 | 伊人国产女 | 中文字幕观看视频 | 色无五月 | 深夜免费小视频 | 97国产一区| www免费在线观看 | 少妇bbw揉bbb欧美 | 欧美在线a视频 | 成人毛片网 | 欧美日韩国产欧美 | 天天超碰 | 色视频网页 | 国产精品丝袜 | 在线综合色 | 精品高清美女精品国产区 | 91一区在线观看 | 国产日韩欧美在线免费观看 | 亚洲欧美日韩在线一区二区 | 中文字幕国产在线 | 久久久国产精品网站 | 国产精品99久久久精品免费观看 | 97久久精品午夜一区二区 | 日韩一区二区免费在线观看 | 婷婷丁香花 | 久久精品精品电影网 | 国产传媒中文字幕 | 91chinesexxx | a视频免费看 | 亚洲人成在线观看 | free,性欧美| 人人人爽 | 国产一级黄色免费看 | 色婷婷综合视频在线观看 | 免费av高清 | 日韩免费 | 在线免费观看视频a | 91麻豆精品国产 | 色五婷婷 | 中文字幕 婷婷 | 欧美日韩在线精品一区二区 | 人人揉人人揉人人揉人人揉97 | 日韩精品在线看 | 国产亚州精品视频 | 色香com.| 国产精品 日韩 欧美 | 在线视频日韩一区 | 国产精国产精品 | 久久久久久久久精 | 91久草视频| av中文字幕在线播放 | 毛片美女网站 | 天天操天天谢 | 亚洲天堂视频在线 | 天天综合网 天天综合色 | 国产麻豆视频 | 国产精品一区二区三区电影 | 99这里精品 | wwxxx日本| 在线播放 日韩专区 | 最近中文字幕 | 日韩美一区二区三区 | 成人h动漫精品一区二 | 国产高清不卡一区二区三区 | 福利一区在线 | 操操综合网 | 精品成人在线 | www色,com | 久久视频这里有久久精品视频11 | 国产精品成人国产乱 | 午夜免费福利片 | 干干操操 | 成年人在线看片 | 操高跟美女 | 一区二区中文字幕在线观看 | 久久精品之| 久久久久久免费网 | 中文字幕在线播放日韩 | avlulu久久精品 | 97超视频在线观看 | 美女视频久久 | 亚洲精品国精品久久99热 | 欧美成人视 | 蜜臀久久99静品久久久久久 | 日韩理论片在线 | 国产一级二级三级在线观看 | 日韩在线观看的 | www成人av| 中文字幕欧美日韩va免费视频 | 日本护士三级少妇三级999 | 激情综合中文娱乐网 | 精品国产视频在线 | 大荫蒂欧美视频另类xxxx | 国产成人一区二区三区电影 | 午夜在线看 | 亚洲黄色软件 | 国产伦理久久精品久久久久_ | 中文字幕视频网站 | 色婷婷88av视频一二三区 | 婷婷在线播放 | 91精品久 | 精品在线播放视频 | 日韩一三区 | 成人性生交大片免费观看网站 | 成人久久亚洲 | 91精品一区国产高清在线gif | 97超碰在线人人 | 嫩草av在线 | 91精品看片| 日韩精品免费在线观看 | 亚洲午夜精品在线观看 | 不卡精品视频 | 在线激情av电影 | 免费男女羞羞的视频网站中文字幕 | 天天操人 | 中国一 片免费观看 | 亚州成人av在线 | 五月天欧美精品 | 在线精品视频免费观看 | 中文字幕在线高清 | 国产91探花 | 91九色在线观看 | 亚洲精品www久久久久久 | av一级二级 | 97在线观看视频国产 | 亚洲全部视频 | 青青河边草免费观看完整版高清 | 午夜精品一区二区三区可下载 | 亚洲欧美日韩精品久久久 |