Package com.google.speedtracer.client.model

Source Code of com.google.speedtracer.client.model.NetworkEventDispatcher

/*
* Copyright 2008 Google Inc.
*
* Licensed 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.google.speedtracer.client.model;

import com.google.gwt.coreext.client.JSOArray;
import com.google.gwt.coreext.client.JsIntegerMap;
import com.google.gwt.coreext.client.JsStringMap;
import com.google.speedtracer.client.model.DataDispatcher.DataDispatcherDelegate;
import com.google.speedtracer.client.model.DataDispatcher.EventRecordDispatcher;
import com.google.speedtracer.client.model.NetworkResponseReceivedEvent.Response;
import com.google.speedtracer.client.model.ResourceUpdateEvent.UpdateResource;
import com.google.speedtracer.shared.EventRecordType;

import java.util.ArrayList;
import java.util.List;

/**
* Native dispatcher which sources Network Events for the UI. Hooks into
* underlying DataInstance.
*/
public class NetworkEventDispatcher implements DataDispatcherDelegate {

  /**
   * Listener Interface for a NetworkEventDispatcher.
   */
  public interface Listener {
    void onNetworkResourceRequestStarted(NetworkResource resource, boolean isRedirect);

    void onNetworkResourceResponseFinished(NetworkResource resource);

    void onNetworkResourceResponseStarted(NetworkResource resource);

    void onNetworkResourceUpdated(NetworkResource resource);
  }

  /**
   * Sets up mapping of NetworkResourceRecord types to their respective
   * handlers.
   *
   * @param proxy the {@link NetworkEventDispatcher}
   * @param typeMap the {@link FastStringMap}
   */
  private static void setNetworkEventCallbacks(
      final NetworkEventDispatcher proxy, JsIntegerMap<EventRecordDispatcher> typeMap) {

    typeMap.put(EventRecordType.RESOURCE_SEND_REQUEST, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        proxy.onNetworkResourceStarted(data.<ResourceWillSendEvent>cast());
      }
    });

    typeMap.put(EventRecordType.RESOURCE_RECEIVE_RESPONSE, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        proxy.onNetworkResourceResponse(data.<ResourceResponseEvent>cast());
      }
    });

    typeMap.put(EventRecordType.RESOURCE_FINISH, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        ResourceFinishEvent finish = data.cast();
        proxy.onNetworkResourceFinished(finish);
      }
    });
   
    typeMap.put(EventRecordType.NETWORK_LOADING_FINISHED, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        ResourceFinishEvent finish = data.cast();
        proxy.onNetworkResourceFinished(finish);
      }
    });

    typeMap.put(EventRecordType.RESOURCE_UPDATED, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        proxy.onNetworkResourceUpdated(data.<ResourceUpdateEvent>cast());
      }
    });

    typeMap.put(EventRecordType.NETWORK_DATA_RECEIVED, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        proxy.onNetworkDataReceived(data.<NetworkDataReceivedEvent>cast());
      }
    });

    typeMap.put(EventRecordType.NETWORK_RESPONSE_RECEIVED, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        proxy.onNetworkResponseReceived(data.<NetworkResponseReceivedEvent>cast());
      }
    });

    typeMap.put(EventRecordType.NETWORK_REQUEST_WILL_BE_SENT, new EventRecordDispatcher() {
      public void onEventRecord(EventRecord data) {
        proxy.onNetworkRequestWillBeSent(data.<NetworkRequestWillBeSentEvent>cast());
      }
    });
  }

  private final List<Listener> listeners = new ArrayList<Listener>();

  private final List<ResourceRecord> networkEvents = new ArrayList<ResourceRecord>();

  private JsStringMap<JSOArray<NetworkResource>> redirects = JsStringMap.create();

  /**
   * Map of NetworkResource POJOs. Information about a network resource is
   * filled in progressively as we get chunks of information about it.
   */
  private final JsStringMap<NetworkResource> resourceStore = JsStringMap.create();

  private final JsIntegerMap<EventRecordDispatcher> typeMap = JsIntegerMap.create();

  public NetworkEventDispatcher() {
    setNetworkEventCallbacks(this, typeMap);
  }

  public void addListener(Listener listener) {
    listeners.add(listener);
  }

  public void clearData() {
    redirects = JsStringMap.create();
    networkEvents.clear();
  }

  public List<ResourceRecord> getNetworkEvents() {
    return networkEvents;
  }

  /**
   * Gets a stored resource from our book keeping, or null if it hasnt been
   * stored before.
   *
   * @param id the request id of our {@link NetworkResource}
   * @return returns the {@link NetworkResource}
   */
  public NetworkResource getResource(String id) {
    return resourceStore.get(id);
  }

  public void onEventRecord(EventRecord data) {
    final EventRecordDispatcher handler = typeMap.get(data.getType());
    if (handler != null) {
      handler.onEventRecord(data);
    }
  }

  public void removeListener(Listener listener) {
    listeners.remove(listener);
  }

  /**
   * @param identifier Resource ID
   * @param url The redirect URL that we are using to match a redirect
   *        candidate.
   */
  private NetworkResource findAndRemoveRedirectCandidate(String identifier, String url) {
    // Look for it.
    JSOArray<NetworkResource> redirectCandidates = redirects.get(identifier);
    if (redirectCandidates == null) {
      return null;
    }

    for (int i = 0; i < redirectCandidates.size(); i++) {
      NetworkResource redirectCandidate = redirectCandidates.get(i);
      if (redirectCandidate.getUrl().equals(url)) {
        // Should not be a concurrent modification, since we now bail out of
        // the loop right after mutating the queue.
        redirectCandidates.splice(i, 1);
        return redirectCandidate;
      }
    }

    return null;
  }

  private void insertRedirectCandidate(String identifier, NetworkResource previousResource) {
    // We have a redirect.
    JSOArray<NetworkResource> redirectQueue = redirects.get(identifier);
    if (redirectQueue == null) {
      redirectQueue = JSOArray.create().cast();
      redirects.put(identifier, redirectQueue);
    }
    redirectQueue.push(previousResource);
  }

  private void onNetworkDataReceived(
      NetworkDataReceivedEvent dataLengthChange) {
    NetworkResource resource = getResource(dataLengthChange.getRequestId());
    if (resource != null) {
      resource.update(dataLengthChange);
    }
  }

  private void onNetworkResponseReceived(NetworkResponseReceivedEvent response) {
    NetworkResource resource = getResource(response.getRequestId());
    if (resource != null) {
      resource.update(response);
    }
  }

  private void onNetworkRequestWillBeSent(NetworkRequestWillBeSentEvent requestWillBeSent) {
    NetworkResource resource = getResource(requestWillBeSent.getRequestId());
    if (resource != null) {
      resource.update(requestWillBeSent);
      // We depend on the fact that any redirects that we encounter will have
      // a corresponding timeline agent event that will add it to the redirects
      // map. We look for one here.
      NetworkRequestWillBeSentEvent.Data data = requestWillBeSent.getData().cast();
      Response redirectResponse = data.getRedirectResponse();
      if (redirectResponse != null) {
        // look for a redirect.
        NetworkResource redirect = findAndRemoveRedirectCandidate(
            requestWillBeSent.getRequestId(), redirectResponse.getUrl());
        if (redirect != null) {
          redirect.updateResponse(redirectResponse);
          redirect.setResponseReceivedTime(requestWillBeSent.getTime());
          redirect.setEndTime(requestWillBeSent.getTime());
          redirectUpdated(redirect);
        }
      }
    }
  }

  private void onNetworkResourceFinished(ResourceFinishEvent resourceFinish) {
    networkEvents.add(resourceFinish);
    NetworkResource resource = getResource(resourceFinish.getRequestId());
    if (resource != null) {
      resource.update(resourceFinish);
      for (int i = 0, n = listeners.size(); i < n; i++) {
        Listener listener = listeners.get(i);
        listener.onNetworkResourceResponseFinished(resource);
      }
    }
  }

  private void onNetworkResourceResponse(ResourceResponseEvent resourceResponse) {
    networkEvents.add(resourceResponse);
    NetworkResource resource = getResource(resourceResponse.getRequestId());
    if (resource != null) {
      resource.update(resourceResponse);
      for (int i = 0, n = listeners.size(); i < n; i++) {
        Listener listener = listeners.get(i);
        listener.onNetworkResourceResponseStarted(resource);
      }
    }
  }

  private void onNetworkResourceStarted(ResourceWillSendEvent resourceStart) {
    networkEvents.add(resourceStart);
    // Check for dupe IDs. If we find one, assume it is a redirect.
    NetworkResource previousResource = getResource(resourceStart.getRequestId());
    boolean isRedirect = false;
    if (previousResource != null) {
      insertRedirectCandidate(previousResource.getIdentifier(), previousResource);
      isRedirect = true;
    }
   
    NetworkResource resource = new NetworkResource(resourceStart);
    resourceStore.put(resourceStart.getRequestId(), resource);
    for (int i = 0, n = listeners.size(); i < n; i++) {
      Listener listener = listeners.get(i);
      listener.onNetworkResourceRequestStarted(resource, isRedirect);
    }
  }

  /**
   * This should now be dead code in the live tracing case, and is only kept to
   * support loading old saved dumps.
   */
  private void onNetworkResourceUpdated(ResourceUpdateEvent update) {
    NetworkResource resource = getResource(update.getRequestId());
    if (resource != null) {
      resource.update(update);
      for (int i = 0, n = listeners.size(); i < n; i++) {
        Listener listener = listeners.get(i);
        listener.onNetworkResourceUpdated(resource);
      }
    } else {
      // We are dealing potentially with an update for a redirect.
      UpdateResource updateResource = update.getUpdate();
      NetworkResource redirectCandidate =
          findAndRemoveRedirectCandidate(update.getRequestId(), updateResource.getUrl());
      if (redirectCandidate != null) {
        redirectCandidate.update(update);
        redirectUpdated(redirectCandidate);
      }
    }
  }

  private void redirectUpdated(NetworkResource redirectCandidate) {
    for (int i = 0, n = listeners.size(); i < n; i++) {
      Listener listener = listeners.get(i);
      listener.onNetworkResourceUpdated(redirectCandidate);
    }
  }
}
TOP

Related Classes of com.google.speedtracer.client.model.NetworkEventDispatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.