weexteam/weex_devtools_android

View on GitHub
inspector/src/main/java/com/taobao/weex/devtools/inspector/protocol/module/Page.java

Summary

Maintainability
B
6 hrs
Test Coverage
/*
 * Copyright (c) 2014-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.taobao.weex.devtools.inspector.protocol.module;

import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;

import com.taobao.weex.devtools.common.ProcessUtil;
import com.taobao.weex.devtools.inspector.domstorage.SharedPreferencesHelper;
import com.taobao.weex.devtools.inspector.jsonrpc.JsonRpcException;
import com.taobao.weex.devtools.inspector.jsonrpc.JsonRpcPeer;
import com.taobao.weex.devtools.inspector.jsonrpc.JsonRpcResult;
import com.taobao.weex.devtools.inspector.jsonrpc.protocol.JsonRpcError;
import com.taobao.weex.devtools.inspector.protocol.ChromeDevtoolsDomain;
import com.taobao.weex.devtools.inspector.protocol.ChromeDevtoolsMethod;
import com.taobao.weex.devtools.inspector.screencast.ScreencastDispatcher;
import com.taobao.weex.devtools.json.ObjectMapper;
import com.taobao.weex.devtools.json.annotation.JsonProperty;
import com.taobao.weex.devtools.json.annotation.JsonValue;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Page implements ChromeDevtoolsDomain {
  private final Context mContext;
  private final ObjectMapper mObjectMapper = new ObjectMapper();

  @Nullable
  private ScreencastDispatcher mScreencastDispatcher;

  public Page(Context context) {
    mContext = context;
  }

  @ChromeDevtoolsMethod
  public void enable(JsonRpcPeer peer, JSONObject params) {
    notifyExecutionContexts(peer);
    sendWelcomeMessage(peer);
  }

  @ChromeDevtoolsMethod
  public void disable(JsonRpcPeer peer, JSONObject params) {
  }

  private void notifyExecutionContexts(JsonRpcPeer peer) {
    ExecutionContextDescription context = new ExecutionContextDescription();
    context.frameId = "1";
    context.id = 1;
    ExecutionContextCreatedParams params = new ExecutionContextCreatedParams();
    params.context = context;
    peer.invokeMethod("Runtime.executionContextCreated", params, null /* callback */);
  }

  private void sendWelcomeMessage(JsonRpcPeer peer) {
    Console.ConsoleMessage message = new Console.ConsoleMessage();
    message.source = Console.MessageSource.JAVASCRIPT;
    message.level = Console.MessageLevel.LOG;
    message.text =
// Note: not using Android resources so we can maintain .jar distribution for now.
        "                                  _               _                 _      \n" +
        "                                 | |             | |               | |     \n" +
        " __      __ ___   ___ __  __   __| |  ___ __   __| |_  ___    ___  | | ___ \n" +
        " \\ \\ /\\ / // _ \\ / _ \\\\ \\/ /  / _` | / _ \\\\ \\ / /| __|/ _ \\  / _ \\ | |/ __|\n" +
        "  \\ V  V /|  __/|  __/ >  <  | (_| ||  __/ \\ V / | |_| (_) || (_) || |\\__ \\\n" +
        "   \\_/\\_/  \\___| \\___|/_/\\_\\  \\__,_| \\___|  \\_/   \\__|\\___/  \\___/ |_||___/\n" +
        "                                                                           \n" +
        "                                                                           \n" +
        "   Welcome to WEEX! Attached to " + ProcessUtil.getProcessName() + "\n";
    Console.MessageAddedRequest messageAddedRequest = new Console.MessageAddedRequest();
    messageAddedRequest.message = message;
    peer.invokeMethod("Console.messageAdded", messageAddedRequest, null /* callback */);
  }

  @ChromeDevtoolsMethod
  public JsonRpcResult getResourceContent(JsonRpcPeer peer, JSONObject params) throws JsonRpcException {
    try {
      String frameId = params.getString("frameId");
      String url = params.getString("url");
      return readResourceContent(frameId, "1");
    } catch (IOException e) {
      throw new JsonRpcException(new JsonRpcError(JsonRpcError.ErrorCode.INTERNAL_ERROR,
              e.toString(),
              null /* data */));
    } catch (JSONException e) {
      throw new JsonRpcException(new JsonRpcError(JsonRpcError.ErrorCode.INTERNAL_ERROR,
              e.toString(),
              null /* data */));
    }
  }

  // TODO:实现具体的读取ResourceContent
  private getResourceContentResponse readResourceContent(String frameId, String url)
          throws IOException, JsonRpcException {
    getResourceContentResponse response = new getResourceContentResponse();
//    ResponseBodyData bodyData;
//    try {
//      bodyData = mResponseBodyFileManager.readFile(url);
//    } catch (OutOfMemoryError e) {
//      throw new JsonRpcException(new JsonRpcError(JsonRpcError.ErrorCode.INTERNAL_ERROR,
//              e.toString(),
//              null /* data */));
//    }
//    response.content = bodyData.data;
//    response.base64Encoded = bodyData.base64Encoded;
    return response;
  }

  // Dog science...
  @ChromeDevtoolsMethod
  public JsonRpcResult getResourceTree(JsonRpcPeer peer, JSONObject params) {
    // The DOMStorage module expects one key/value store per "security origin" which has a 1:1
    // relationship with resource tree frames.
    List<String> prefsTags = SharedPreferencesHelper.getSharedPreferenceTags(mContext);
    Iterator<String> prefsTagsIter = prefsTags.iterator();

    FrameResourceTree tree = createSimpleFrameResourceTree(
        "1",
        null /* parentId */,
        "Weex",
        prefsTagsIter.hasNext() ? prefsTagsIter.next() : "");
    if (tree.childFrames == null) {
      tree.childFrames = new ArrayList<FrameResourceTree>();
    }

    int nextChildFrameId = 1;
    while (prefsTagsIter.hasNext()) {
      String frameId = "1." + (nextChildFrameId++);
      String prefsTag = prefsTagsIter.next();
      FrameResourceTree child = createSimpleFrameResourceTree(
          frameId,
          "1",
          "Child #" + frameId,
          prefsTag);
      tree.childFrames.add(child);
    }

    GetResourceTreeParams resultParams = new GetResourceTreeParams();
    resultParams.frameTree = tree;
    return resultParams;
  }

  private static FrameResourceTree createSimpleFrameResourceTree(
      String id,
      String parentId,
      String name,
      String securityOrigin) {
    Frame frame = new Frame();
    frame.id = id;
    frame.parentId = parentId;
    frame.loaderId = "1";
    frame.name = name;
    frame.url = "";
    frame.securityOrigin = securityOrigin;
    frame.mimeType = "text/plain";
    FrameResourceTree tree = new FrameResourceTree();
    tree.frame = frame;
    tree.resources = Collections.emptyList();
    tree.childFrames = null;
    return tree;
  }

  private static FrameResourceTree createMockFrameResourceTree(
          String id,
          String parentId,
          String name,
          String securityOrigin) {
    Frame frame = new Frame();
    frame.id = id;
    frame.parentId = parentId;
    frame.loaderId = "2";
    frame.name = name;
    frame.url = "http://www.sina.com";
    frame.securityOrigin = securityOrigin;
    frame.mimeType = "text/plain";
    FrameResourceTree tree = new FrameResourceTree();
    tree.frame = frame;
    tree.resources = createMockResource();// createMockResource();
    tree.childFrames = null;
    Log.v("FrameResourceTree", "frame : " + ", name : " + frame.name + ", mimeType : " + frame.mimeType);
    return tree;
  }

  private static List<Resource> createMockResource() {
    ArrayList<Resource> list = new ArrayList<Resource>();
    Resource resource = new Resource();
    resource.url="http://apod.nasa.gov/apod/ap160601.html";
    resource.type= ResourceType.DOCUMENT;
    resource.mimeType="text/HTML";

    Resource resource2 = new Resource();
    resource2.url="http://30.10.216.161:12580/examples/build/hello.js";
    resource2.type= ResourceType.SCRIPT;
    resource2.mimeType="text/javascript";
    list.add(resource);
    list.add(resource2);

    return list;
  }

  @ChromeDevtoolsMethod
  public JsonRpcResult canScreencast(JsonRpcPeer peer, JSONObject params) {
    return new SimpleBooleanResult(true);
  }

  @ChromeDevtoolsMethod
  public JsonRpcResult hasTouchInputs(JsonRpcPeer peer, JSONObject params) {
    return new SimpleBooleanResult(false);
  }

  @ChromeDevtoolsMethod
  public void setDeviceMetricsOverride(JsonRpcPeer peer, JSONObject params) {
  }

  @ChromeDevtoolsMethod
  public void clearDeviceOrientationOverride(JsonRpcPeer peer, JSONObject params) {
  }

  @ChromeDevtoolsMethod
  public void startScreencast(final JsonRpcPeer peer, JSONObject params) {
    final StartScreencastRequest request = mObjectMapper.convertValue(
        params, StartScreencastRequest.class);
    if (mScreencastDispatcher == null) {
      mScreencastDispatcher = new ScreencastDispatcher();
      mScreencastDispatcher.startScreencast(peer, request);
    }
  }

  @ChromeDevtoolsMethod
  public void stopScreencast(JsonRpcPeer peer, JSONObject params) {
    if (mScreencastDispatcher != null) {
      mScreencastDispatcher.stopScreencast();
      mScreencastDispatcher = null;
    }
  }

  @ChromeDevtoolsMethod
  public void screencastFrameAck(JsonRpcPeer peer, JSONObject params) {
    // Nothing to do here, just need to make sure Chrome doesn't get an error that this method
    // isn't implemented
  }

  @ChromeDevtoolsMethod
  public void clearGeolocationOverride(JsonRpcPeer peer, JSONObject params) {
  }

  @ChromeDevtoolsMethod
  public void setTouchEmulationEnabled(JsonRpcPeer peer, JSONObject params) {
  }

  @ChromeDevtoolsMethod
  public void setEmulatedMedia(JsonRpcPeer peer, JSONObject params) {
  }

  @ChromeDevtoolsMethod
  public void setShowViewportSizeOnResize(JsonRpcPeer peer, JSONObject params) {
  }

  private static class getResourceContentResponse implements JsonRpcResult {
    @JsonProperty(required = true)
    public String content;

    @JsonProperty(required = true)
    public boolean base64Encoded;
  }

  private static class GetResourceTreeParams implements JsonRpcResult {
    @JsonProperty(required = true)
    public FrameResourceTree frameTree;
  }

  private static class FrameResourceTree {
    @JsonProperty(required = true)
    public Frame frame;

    @JsonProperty
    public List<FrameResourceTree> childFrames;

    @JsonProperty(required = true)
    public List<Resource> resources;
  }

  private static class Frame {
    @JsonProperty(required = true)
    public String id;

    @JsonProperty
    public String parentId;

    @JsonProperty(required = true)
    public String loaderId;

    @JsonProperty
    public String name;

    @JsonProperty(required = true)
    public String url;

    @JsonProperty(required = true)
    public String securityOrigin;

    @JsonProperty(required = true)
    public String mimeType;
  }

  private static class Resource {
    @JsonProperty(required = true)
    public String url;
    @JsonProperty(required = true)
    public ResourceType type;
    @JsonProperty(required = true)
    public String mimeType;
    @JsonProperty
    public boolean failed;
    @JsonProperty
    public boolean canceled;
  }

  public enum ResourceType {
    DOCUMENT("Document"),
    STYLESHEET("Stylesheet"),
    IMAGE("Image"),
    FONT("Font"),
    SCRIPT("Script"),
    XHR("XHR"),
    WEBSOCKET("WebSocket"),
    OTHER("Other");

    private final String mProtocolValue;

    private ResourceType(String protocolValue) {
      mProtocolValue = protocolValue;
    }

    @JsonValue
    public String getProtocolValue() {
      return mProtocolValue;
    }
  }

  private static class ExecutionContextCreatedParams {
    @JsonProperty(required = true)
    public ExecutionContextDescription context;
  }

  private static class ExecutionContextDescription {
    @JsonProperty(required = true)
    public String frameId;

    @JsonProperty(required = true)
    public int id;
  }

  public static class ScreencastFrameEvent {
    @JsonProperty(required = true)
    public String data;

    @JsonProperty(required = true)
    public ScreencastFrameEventMetadata metadata;
  }

  public static class ScreencastFrameEventMetadata {
    @JsonProperty(required = true)
    public float pageScaleFactor;
    @JsonProperty(required = true)
    public int offsetTop;
    @JsonProperty(required = true)
    public int deviceWidth;
    @JsonProperty(required = true)
    public int deviceHeight;
    @JsonProperty(required = true)
    public int scrollOffsetX;
    @JsonProperty(required = true)
    public int scrollOffsetY;
  }

  public static class StartScreencastRequest {
    @JsonProperty
    public String format;
    @JsonProperty
    public int quality;
    @JsonProperty
    public int maxWidth;
    @JsonProperty
    public int maxHeight;
  }
}