MediaUploader = function(options) {
  var noop = function() {};
  this.file = options.file;
  this.contentType = options.contentType || this.file.type || 'application/octet-stream';
  this.metadata = options.metadata || {
    'title': this.file.name,
    'mimeType': this.contentType
  };
  this.token = options.token;
  this.onComplete = options.onComplete || noop;
  this.onProgress = options.onProgress || noop;
  this.onError = options.onError || noop;
  this.offset = options.offset || 0;
  this.chunkSize = options.chunkSize || 0;
  this.retryHandler = new RetryHandler();

  this.url = options.url;
  if (!this.url) {
    var params = options.params || {};
    params.uploadType = 'resumable';
    this.url = this.buildUrl_(options.fileId, params, options.baseUrl);
  }
  this.httpMethod = options.fileId ? 'PUT' : 'POST';
}
Helper class for resumable uploads using XHR/CORS. Can upload any Blob-like item, whether
files or in-memory constructs.

@example
var content = new Blob(["Hello world"], {"type": "text/plain"});
var uploader = new MediaUploader({
  file: content,
  token: accessToken,
  onComplete: function(data) { ... }
  onError: function(data) { ... }
});
uploader.upload();

@constructor
@param {object} options Hash of options
@param {string} options.token Access token
@param {blob} options.file Blob-like item to upload
@param {string} [options.fileId] ID of file if replacing
@param {object} [options.params] Additional query parameters
@param {string} [options.contentType] Content-type, if overriding the type of the blob.
@param {object} [options.metadata] File metadata
@param {function} [options.onComplete] Callback for when upload is complete
@param {function} [options.onProgress] Callback for status for the in-progress upload
@param {function} [options.onError] Callback if upload fails