blob: 15d9cf2f7da0d9f8c4ac7673e8430fa896c986c2 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.taobao.weex;
import android.net.Uri;
import android.text.TextUtils;
import com.taobao.weex.adapter.IWXHttpAdapter;
import com.taobao.weex.adapter.IWXUserTrackAdapter;
import com.taobao.weex.common.WXErrorCode;
import com.taobao.weex.common.WXPerformance;
import com.taobao.weex.common.WXRenderStrategy;
import com.taobao.weex.common.WXResponse;
import com.taobao.weex.performance.WXInstanceApm;
import com.taobao.weex.tracing.WXTracing;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.tools.LogDetail;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* load bundle js listener
*/
public class WXHttpListener implements IWXHttpAdapter.OnHttpListener {
private String pageName;
private Map<String, Object> options;
private String jsonInitData;
private WXRenderStrategy flag;
private WXSDKInstance instance;
private long startRequestTime;
private int traceId;
private WXPerformance mWXPerformance;
private WXInstanceApm mApmForInstance;
private IWXUserTrackAdapter mUserTrackAdapter;
public boolean isPreDownLoadMode = false;
private boolean isInstanceReady =false;
private boolean isResponseHasWait = false;
private WXResponse mResponse;
private LogDetail mLogDetail;
private String mBundleUrl;
public WXHttpListener(WXSDKInstance instance) {
if(instance != null) {
mLogDetail = instance.mTimeCalculator.createLogDetail("downloadBundleJS");
}
this.instance = instance;
this.traceId = WXTracing.nextId();
this.mWXPerformance = instance.getWXPerformance();
this.mApmForInstance = instance.getApmForInstance();
this.mUserTrackAdapter = WXSDKManager.getInstance().getIWXUserTrackAdapter();
if (WXTracing.isAvailable()) {
WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", instance.getInstanceId(), -1);
event.iid = instance.getInstanceId();
event.tname = "Network";
event.ph = "B";
event.traceId = traceId;
event.submit();
}
}
public WXHttpListener(WXSDKInstance instance, String bundleUrl) {
this(instance);
this.startRequestTime = System.currentTimeMillis();
this.mBundleUrl = bundleUrl;
}
public WXHttpListener(WXSDKInstance instance, String pageName, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag, long startRequestTime) {
this(instance);
this.pageName = pageName;
this.options = options;
this.jsonInitData = jsonInitData;
this.flag = flag;
this.startRequestTime = startRequestTime;
this.mBundleUrl = instance.getBundleUrl();
}
public void setSDKInstance(WXSDKInstance instance) {
this.instance = instance;
}
protected WXSDKInstance getInstance() {
return instance;
}
@Override
public void onHttpStart() {
if (this.instance != null
&& this.instance.getWXStatisticsListener() != null) {
this.instance.getWXStatisticsListener().onHttpStart();
if(mLogDetail != null) {
mLogDetail.taskStart();
}
}
}
@Override
public void onHeadersReceived(int statusCode, Map<String,List<String>> headers) {
if (this.instance != null
&& this.instance.getWXStatisticsListener() != null) {
this.instance.getWXStatisticsListener().onHeadersReceived();
this.instance.onHttpStart();
}
if(this.instance != null
&& this.instance.responseHeaders != null
&& headers != null){
this.instance.responseHeaders.putAll(headers);
}
}
@Override
public void onHttpUploadProgress(int uploadProgress) {
}
@Override
public void onHttpResponseProgress(int loadedLength) {
instance.getApmForInstance().extInfo.put(WXInstanceApm.VALUE_BUNDLE_LOAD_LENGTH,loadedLength);
}
@Override
public void onHttpFinish(WXResponse response) {
if(mLogDetail != null) {
mLogDetail.taskEnd();
}
if (this.instance != null
&& this.instance.getWXStatisticsListener() != null) {
this.instance.getWXStatisticsListener().onHttpFinish();
}
if (WXTracing.isAvailable()) {
WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", instance.getInstanceId(), -1);
event.traceId = traceId;
event.tname = "Network";
event.ph = "E";
event.extParams = new HashMap<>();
if (response != null && response.originalData != null) {
event.extParams.put("BundleSize", response.originalData.length);
}
event.submit();
}
mWXPerformance.networkTime = System.currentTimeMillis() - startRequestTime;
if(null!= response && response.extendParams!=null){
mApmForInstance.updateRecordInfo(response.extendParams);
Object actualNetworkTime=response.extendParams.get("actualNetworkTime");
mWXPerformance.actualNetworkTime=actualNetworkTime instanceof Long?(long)actualNetworkTime:0;
Object pureNetworkTime=response.extendParams.get("pureNetworkTime");
mWXPerformance.pureNetworkTime=pureNetworkTime instanceof Long?(long)pureNetworkTime:0;
Object connectionType=response.extendParams.get("connectionType");
mWXPerformance.connectionType=connectionType instanceof String?(String)connectionType:"";
Object packageSpendTime=response.extendParams.get("packageSpendTime");
mWXPerformance.packageSpendTime=packageSpendTime instanceof Long ?(long)packageSpendTime:0;
Object syncTaskTime=response.extendParams.get("syncTaskTime");
mWXPerformance.syncTaskTime=syncTaskTime instanceof Long ?(long)syncTaskTime:0;
Object requestType=response.extendParams.get("requestType");
mWXPerformance.requestType=requestType instanceof String?(String)requestType:"none";
Object cacheType = response.extendParams.get(WXPerformance.Dimension.cacheType.toString());
if(cacheType instanceof String){
mWXPerformance.cacheType = (String) cacheType;
}
Object zCacheInfo = response.extendParams.get("zCacheInfo");
mWXPerformance.zCacheInfo = zCacheInfo instanceof String?(String)zCacheInfo:"";
if(isNet(mWXPerformance.requestType) && mUserTrackAdapter!=null){
WXPerformance performance=new WXPerformance(instance.getInstanceId());
if(!TextUtils.isEmpty(mBundleUrl)){
try {
performance.args= Uri.parse(mBundleUrl).buildUpon().clearQuery().toString();
} catch (Exception e) {
performance.args=pageName;
}
}
if(!"200".equals(response.statusCode)){
performance.errCode= WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
performance.appendErrMsg(response.errorCode);
performance.appendErrMsg("|");
performance.appendErrMsg(response.errorMsg);
}else if("200".equals(response.statusCode) && (response.originalData==null || response.originalData.length<=0)){
performance.errCode=WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
performance.appendErrMsg(response.statusCode);
performance.appendErrMsg("|template is null!");
}else {
performance.errCode=WXErrorCode.WX_SUCCESS.getErrorCode();
}
if (mUserTrackAdapter != null) {
mUserTrackAdapter.commit(instance.getContext(), null, IWXUserTrackAdapter.JS_DOWNLOAD, performance, null);
}
}
}
if (isPreDownLoadMode){
if (isInstanceReady){
WXLogUtils.d("test->", "DownLoad didHttpFinish on http" );
didHttpFinish(response);
}else {
WXLogUtils.d("test->", "DownLoad end before activity created" );
mResponse = response;
isResponseHasWait = true;
}
}else {
didHttpFinish(response);
}
}
public void onInstanceReady(){
if (!isPreDownLoadMode){
return;
}
this.isInstanceReady = true;
if (isResponseHasWait){
WXLogUtils.d("test->", "preDownLoad didHttpFinish on ready" );
this.didHttpFinish(mResponse);
}
}
private void didHttpFinish(WXResponse response){
String wxErrorCode = WXInstanceApm.VALUE_ERROR_CODE_DEFAULT;
if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) {
mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_END);
onSuccess(response);
// check content-type
} else if (TextUtils.equals(WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(),
response.statusCode)) {
WXLogUtils.e("user intercept: WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR");
wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode();
instance.onRenderError(wxErrorCode,
"|response.errorMsg==" + response.errorMsg +
"|instance bundleUrl = \n" + instance.getBundleUrl() +
"|instance requestUrl = \n" + Uri.decode(WXSDKInstance.requestUrl)
);
onFail(response);
// check content-length
} else if (response!=null && response.originalData!=null && TextUtils.equals("-206", response.statusCode)) {
WXLogUtils.e("user intercept: WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED");
wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode();
instance.onRenderError(wxErrorCode ,
WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode() +
"|response.errorMsg==" + response.errorMsg
);
onFail(response);
}
else {
wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getErrorCode();
instance.onRenderError(wxErrorCode,
response.errorMsg);
onFail(response);
}
if (!WXInstanceApm.VALUE_ERROR_CODE_DEFAULT.equals(wxErrorCode)){
mApmForInstance.addProperty(WXInstanceApm.KEY_PROPERTIES_ERROR_CODE,wxErrorCode);
}
}
private boolean isNet(String requestType){
return "network".equals(requestType) || "2g".equals(requestType) || "3g".equals(requestType)
|| "4g".equals(requestType) || "wifi".equals(requestType) || "other".equals(requestType)
|| "unknown".equals(requestType);
}
public void onSuccess(WXResponse response) {
if (flag==WXRenderStrategy.DATA_RENDER_BINARY){
instance.render(pageName, response.originalData, options, jsonInitData);
}else {
String template = new String(response.originalData);
instance.render(pageName, template, options, jsonInitData, flag);
}
}
public void onFail(WXResponse response) {
}
}