More Chromium Blob hacking to switch from bloburls to blobuuids.

This cr patch is needed prior to continuing work over on the blnk side. One of many in multi-side-patch-tango.

This change introduces a compile time flag, USE_BLOB_UUIDS, to switch over to the new model. The old and new style of identifying these things are currently in place at the webkit api level. This flag tells chromium which to use. Blink is currently still using the old style urls and USE_BLOB_UUIDS is not defined. The flag will be set in the Blink patch that switches it over (it will be defined in WebBlobData.h).

There is one blob use case (feedback extension api) up in /chrome that is handled a little differently. Instead of the compile time flag, it relies on a runtime check due to layering/deps rules. There is nothing in the contentAPI about blobs yet and that consumer relies on reading the blob data by urlfetching given only the internalurl/uuid.

Also in this change are some minor cleanup to better indicate when we're working with a FileSystemUrl in particular.

TBR=kalman
BUG=174200

Review URL: https://chromiumcodereview.appspot.com/23898006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224906 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/api/feedback_private/blob_reader.cc b/chrome/browser/extensions/api/feedback_private/blob_reader.cc
index 3f2ee234..4ee07c973 100644
--- a/chrome/browser/extensions/api/feedback_private/blob_reader.cc
+++ b/chrome/browser/extensions/api/feedback_private/blob_reader.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/api/feedback_private/blob_reader.h"
 
+#include "base/strings/string_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/url_request/url_fetcher.h"
@@ -11,12 +12,20 @@
 #include "net/url_request/url_request_context_getter.h"
 
 BlobReader::BlobReader(Profile* profile,
-                       const GURL& blob_url,
+                       const std::string& blob_uuid,
                        BlobReadCallback callback)
     : callback_(callback) {
-  fetcher_ = net::URLFetcher::Create(
+  GURL blob_url;
+  if (StartsWithASCII(blob_uuid, "blob:blobinternal", true)) {
+    // TODO(michaeln): remove support for deprecated blob urls
+    blob_url = GURL(blob_uuid);
+  } else {
+    blob_url = GURL(std::string("blob:uuid/") + blob_uuid);
+  }
+  DCHECK(blob_url.is_valid());
+  fetcher_.reset(net::URLFetcher::Create(
       blob_url, net::URLFetcher::GET,
-      this);
+      this));
   fetcher_->SetRequestContext(profile->GetRequestContext());
 }
 
diff --git a/chrome/browser/extensions/api/feedback_private/blob_reader.h b/chrome/browser/extensions/api/feedback_private/blob_reader.h
index 6c05b209..455d2c05 100644
--- a/chrome/browser/extensions/api/feedback_private/blob_reader.h
+++ b/chrome/browser/extensions/api/feedback_private/blob_reader.h
@@ -25,7 +25,7 @@
       BlobReadCallback;
 
   BlobReader(Profile* profile,
-             const GURL& blob_url,
+             const std::string& blob_uuid,
              BlobReadCallback callback);
   virtual ~BlobReader();
 
@@ -36,7 +36,7 @@
   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
   BlobReadCallback callback_;
-  net::URLFetcher* fetcher_;
+  scoped_ptr<net::URLFetcher> fetcher_;
 
   DISALLOW_COPY_AND_ASSIGN(BlobReader);
 };
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
index 98c0769..eeb263b 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
@@ -142,14 +142,15 @@
 
   const FeedbackInfo &feedback_info = params->feedback;
 
-  std::string attached_file_url, screenshot_url;
-  if (feedback_info.attached_file_blob_url.get() &&
-      !feedback_info.attached_file_blob_url->empty())
-    attached_file_url = *feedback_info.attached_file_blob_url;
+  std::string attached_file_uuid;
+  if (feedback_info.attached_file_blob_uuid.get() &&
+      !feedback_info.attached_file_blob_uuid->empty())
+    attached_file_uuid = *feedback_info.attached_file_blob_uuid;
 
-  if (feedback_info.screenshot_blob_url.get() &&
-      !feedback_info.screenshot_blob_url->empty())
-    screenshot_url = *feedback_info.screenshot_blob_url;
+  std::string screenshot_uuid;
+  if (feedback_info.screenshot_blob_uuid.get() &&
+      !feedback_info.screenshot_blob_uuid->empty())
+    screenshot_uuid = *feedback_info.screenshot_blob_uuid;
 
   // Populate feedback data.
   scoped_refptr<FeedbackData> feedback_data(new FeedbackData());
@@ -163,14 +164,14 @@
   if (feedback_info.email.get())
     feedback_data->set_user_email(*feedback_info.email.get());
 
-  if (!attached_file_url.empty()) {
+  if (!attached_file_uuid.empty()) {
     feedback_data->set_attached_filename(
         (*feedback_info.attached_file.get()).name);
-    feedback_data->set_attached_file_url(GURL(attached_file_url));
+    feedback_data->set_attached_file_uuid(attached_file_uuid);
   }
 
-  if (!screenshot_url.empty())
-    feedback_data->set_screenshot_url(GURL(screenshot_url));
+  if (!screenshot_uuid.empty())
+    feedback_data->set_screenshot_uuid(screenshot_uuid);
 
   if (feedback_info.trace_id.get()) {
     feedback_data->set_trace_id(*feedback_info.trace_id.get());
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.cc b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
index a4102ed..b16f1ad 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_service.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
@@ -42,19 +42,19 @@
   send_feedback_callback_ = callback;
   feedback_data_ = feedback_data;
 
-  if (feedback_data_->attached_file_url().is_valid()) {
+  if (!feedback_data_->attached_file_uuid().empty()) {
     // Self-deleting object.
     BlobReader* attached_file_reader = new BlobReader(
-        profile, feedback_data_->attached_file_url(),
+        profile, feedback_data_->attached_file_uuid(),
         base::Bind(&FeedbackService::AttachedFileCallback,
                    GetWeakPtr()));
     attached_file_reader->Start();
   }
 
-  if (feedback_data_->screenshot_url().is_valid()) {
+  if (!feedback_data_->screenshot_uuid().empty()) {
     // Self-deleting object.
     BlobReader* screenshot_reader = new BlobReader(
-        profile, feedback_data_->screenshot_url(),
+        profile, feedback_data_->screenshot_uuid(),
         base::Bind(&FeedbackService::ScreenshotCallback,
                    GetWeakPtr()));
     screenshot_reader->Start();
@@ -65,7 +65,7 @@
 
 void FeedbackService::AttachedFileCallback(scoped_ptr<std::string> data) {
   if (!data.get())
-    feedback_data_->set_attached_file_url(GURL());
+    feedback_data_->set_attached_file_uuid(std::string());
   else
     feedback_data_->set_attached_filedata(data.Pass());
 
@@ -74,7 +74,7 @@
 
 void FeedbackService::ScreenshotCallback(scoped_ptr<std::string> data) {
   if (!data.get())
-    feedback_data_->set_screenshot_url(GURL());
+    feedback_data_->set_screenshot_uuid(std::string());
   else
     feedback_data_->set_image(data.Pass());
 
@@ -90,10 +90,10 @@
   //     and the read callback has updated the associated data on the feedback
   //     object.
   bool attached_file_completed =
-      !feedback_data_->attached_file_url().is_valid() ||
+      feedback_data_->attached_file_uuid().empty() ||
       feedback_data_->attached_filedata();
   bool screenshot_completed =
-      !feedback_data_->screenshot_url().is_valid() ||
+      !feedback_data_->screenshot_uuid().empty() ||
       feedback_data_->image();
 
   if (screenshot_completed && attached_file_completed) {
diff --git a/chrome/browser/feedback/feedback_data.h b/chrome/browser/feedback/feedback_data.h
index 4b11550..0e723fb 100644
--- a/chrome/browser/feedback/feedback_data.h
+++ b/chrome/browser/feedback/feedback_data.h
@@ -58,9 +58,9 @@
   const std::string& user_email() const { return user_email_; }
   std::string* image() const { return image_.get(); }
   const std::string attached_filename() const { return attached_filename_; }
-  const GURL attached_file_url() const { return attached_file_url_; }
+  const std::string attached_file_uuid() const { return attached_file_uuid_; }
   std::string* attached_filedata() const { return attached_filedata_.get(); }
-  const GURL screenshot_url() const { return screenshot_url_; }
+  const std::string screenshot_uuid() const { return screenshot_uuid_; }
   int trace_id() const { return trace_id_; }
   SystemLogsMap* sys_info() const { return sys_info_.get(); }
   std::string* compressed_logs() const { return compressed_logs_.get(); }
@@ -84,8 +84,12 @@
   void set_attached_filedata(scoped_ptr<std::string> attached_filedata) {
     attached_filedata_ = attached_filedata.Pass();
   }
-  void set_attached_file_url(const GURL& url) { attached_file_url_ = url; }
-  void set_screenshot_url(const GURL& url) { screenshot_url_ = url; }
+  void set_attached_file_uuid(const std::string& uuid) {
+    attached_file_uuid_ = uuid;
+  }
+  void set_screenshot_uuid(const std::string& uuid) {
+    screenshot_uuid_ = uuid;
+  }
   void set_trace_id(int trace_id) { trace_id_ = trace_id; }
 
  private:
@@ -105,8 +109,8 @@
   std::string attached_filename_;
   scoped_ptr<std::string> attached_filedata_;
 
-  GURL attached_file_url_;
-  GURL screenshot_url_;
+  std::string attached_file_uuid_;
+  std::string screenshot_uuid_;
 
   int trace_id_;
 
diff --git a/chrome/common/extensions/api/feedback_private.idl b/chrome/common/extensions/api/feedback_private.idl
index 5641caa..93f799c 100644
--- a/chrome/common/extensions/api/feedback_private.idl
+++ b/chrome/common/extensions/api/feedback_private.idl
@@ -48,9 +48,9 @@
     SystemInformation[]? systemInformation;
 
     // TODO(rkc): Remove these once we have bindings to send blobs to Chrome.
-    // Used internally to store the blob Url after parameter customization.
-    DOMString? attachedFileBlobUrl;
-    DOMString? screenshotBlobUrl;
+    // Used internally to store the blob uuid after parameter customization.
+    DOMString? attachedFileBlobUuid;
+    DOMString? screenshotBlobUuid;
   };
 
   // Status of the sending of a feedback report.
diff --git a/chrome/renderer/extensions/feedback_private_custom_bindings.cc b/chrome/renderer/extensions/feedback_private_custom_bindings.cc
index a4fc075e..64e8373 100644
--- a/chrome/renderer/extensions/feedback_private_custom_bindings.cc
+++ b/chrome/renderer/extensions/feedback_private_custom_bindings.cc
@@ -11,10 +11,14 @@
 
 namespace {
 
-void GetBlobUrl(const v8::FunctionCallbackInfo<v8::Value> &args) {
+void GetBlobUuid(const v8::FunctionCallbackInfo<v8::Value> &args) {
   DCHECK(args.Length() == 1);
   WebKit::WebBlob blob = WebKit::WebBlob::fromV8Value(args[0]);
+#ifdef USE_BLOB_UUIDS
+  args.GetReturnValue().Set(v8::String::New(blob.uuid().utf8().data()));
+#else
   args.GetReturnValue().Set(v8::String::New(blob.url().spec().data()));
+#endif
 }
 
 }  // namespace
@@ -24,7 +28,7 @@
 FeedbackPrivateCustomBindings::FeedbackPrivateCustomBindings(
     Dispatcher* dispatcher,
     ChromeV8Context* context) : ChromeV8Extension(dispatcher, context) {
-  RouteFunction("GetBlobUrl", base::Bind(&GetBlobUrl));
+  RouteFunction("GetBlobUuid", base::Bind(&GetBlobUuid));
 }
 
 }  // namespace extensions
diff --git a/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js b/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
index 6b2122b9..cca402fe 100644
--- a/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
@@ -12,18 +12,18 @@
   var apiFunctions = bindingsAPI.apiFunctions;
   apiFunctions.setUpdateArgumentsPostValidate(
       "sendFeedback", function(feedbackInfo, callback) {
-    var attachedFileBlobUrl = '';
-    var screenshotBlobUrl = '';
+    var attachedFileBlobUuid = '';
+    var screenshotBlobUuid = '';
 
     if (feedbackInfo.attachedFile)
-      attachedFileBlobUrl =
-          feedbackPrivateNatives.GetBlobUrl(feedbackInfo.attachedFile.data);
+      attachedFileBlobUuid =
+          feedbackPrivateNatives.GetBlobUuid(feedbackInfo.attachedFile.data);
     if (feedbackInfo.screenshot)
-      screenshotBlobUrl =
-          feedbackPrivateNatives.GetBlobUrl(feedbackInfo.screenshot);
+      screenshotBlobUuid =
+          feedbackPrivateNatives.GetBlobUuid(feedbackInfo.screenshot);
 
-    feedbackInfo.attachedFileBlobUrl = attachedFileBlobUrl;
-    feedbackInfo.screenshotBlobUrl = screenshotBlobUrl;
+    feedbackInfo.attachedFileBlobUuid = attachedFileBlobUuid;
+    feedbackInfo.screenshotBlobUuid = screenshotBlobUuid;
 
     return [feedbackInfo, callback];
   });
diff --git a/content/child/webblobregistry_impl.cc b/content/child/webblobregistry_impl.cc
index b701c03..fb3ffd1 100644
--- a/content/child/webblobregistry_impl.cc
+++ b/content/child/webblobregistry_impl.cc
@@ -69,21 +69,28 @@
       case WebBlobData::Item::TypeBlob:
         if (data_item.length) {
           webkit_blob::BlobData::Item item;
+#ifdef USE_BLOB_UUIDS
+          item.SetToBlobRange(
+              data_item.blobUUID.utf8(),
+              static_cast<uint64>(data_item.offset),
+              static_cast<uint64>(data_item.length));
+#else
           item.SetToBlobUrlRange(
               data_item.blobURL,
               static_cast<uint64>(data_item.offset),
               static_cast<uint64>(data_item.length));
+#endif
           sender_->Send(
               new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
         }
         break;
-      case WebBlobData::Item::TypeURL:
+      case WebBlobData::Item::TypeFileSystemURL:
         if (data_item.length) {
           // We only support filesystem URL as of now.
-          DCHECK(GURL(data_item.url).SchemeIsFileSystem());
+          DCHECK(GURL(data_item.fileSystemURL).SchemeIsFileSystem());
           webkit_blob::BlobData::Item item;
           item.SetToFileSystemUrlRange(
-              data_item.url,
+              data_item.fileSystemURL,
               static_cast<uint64>(data_item.offset),
               static_cast<uint64>(data_item.length),
               base::Time::FromDoubleT(data_item.expectedModificationTime));
diff --git a/content/common/page_state_serialization.cc b/content/common/page_state_serialization.cc
index 3656c53a..f0add0b 100644
--- a/content/common/page_state_serialization.cc
+++ b/content/common/page_state_serialization.cc
@@ -58,6 +58,15 @@
   http_body->elements.push_back(element);
 }
 
+#ifdef USE_BLOB_UUIDS
+void AppendBlobToHttpBody(ExplodedHttpBody* http_body,
+                          const std::string& uuid) {
+  ExplodedHttpBodyElement element;
+  element.type = WebKit::WebHTTPBody::Element::TypeBlob;
+  element.blob_uuid = uuid;
+  http_body->elements.push_back(element);
+}
+#else
 void DeprecatedAppendBlobToHttpBody(ExplodedHttpBody* http_body,
                                     const GURL& url) {
   ExplodedHttpBodyElement element;
@@ -65,6 +74,7 @@
   element.deprecated_blob_url = url;
   http_body->elements.push_back(element);
 }
+#endif
 
 //----------------------------------------------------------------------------
 
@@ -185,12 +195,21 @@
 // 12: Adds support for contains_passwords in HTTP body
 // 13: Adds support for URL (FileSystem URL)
 // 14: Adds list of referenced files, version written only for first item.
+// 15: Switched from blob urls to blob uuids.
 //
 // NOTE: If the version is -1, then the pickle contains only a URL string.
 // See ReadPageState.
 //
 const int kMinVersion = 11;
+#ifdef USE_BLOB_UUIDS
+// This is not used yet, if a version bump is needed in advance of
+// this becoming used, bump both values by one and fixup the comment
+// and change the test for '15' in ReadHttpBody().
+// -- michaeln
+const int kCurrentVersion = 15;
+#else
 const int kCurrentVersion = 14;
+#endif
 
 // A bunch of convenience functions to read/write to SerializeObjects.  The
 // de-serializers assume the input data will be in the correct format and fall
@@ -281,6 +300,18 @@
   return GURL();
 }
 
+void WriteStdString(const std::string& s, SerializeObject* obj) {
+  obj->pickle.WriteString(s);
+}
+
+std::string ReadStdString(SerializeObject* obj) {
+  std::string s;
+  if (obj->pickle.ReadString(&obj->iter, &s))
+    return s;
+  obj->parse_error = true;
+  return std::string();
+}
+
 // WriteString pickles the NullableString16 as <int length><char16* data>.
 // If length == -1, then the NullableString16 itself is null.  Otherwise the
 // length is the number of char16 (not bytes) in the NullableString16.
@@ -404,7 +435,11 @@
       WriteReal(element.file_modification_time, obj);
     } else {
       DCHECK(element.type == WebKit::WebHTTPBody::Element::TypeBlob);
+#ifdef USE_BLOB_UUIDS
+      WriteStdString(element.blob_uuid, obj);
+#else
       WriteGURL(element.deprecated_blob_url, obj);
+#endif
     }
   }
   WriteInteger64(http_body.identifier, obj);
@@ -444,8 +479,17 @@
       AppendURLRangeToHttpBody(http_body, url, file_start, file_length,
                                file_modification_time);
     } else if (type == WebKit::WebHTTPBody::Element::TypeBlob) {
+#ifdef USE_BLOB_UUIDS
+      if (obj->version >= 15) {
+        std::string blob_uuid = ReadStdString(obj);
+        AppendBlobToHttpBody(http_body, blob_uuid);
+      } else {
+        ReadGURL(obj); // Skip the obsolete blob url value.
+      }
+#else
       GURL blob_url = ReadGURL(obj);
       DeprecatedAppendBlobToHttpBody(http_body, blob_url);
+#endif
     }
   }
   http_body->identifier = ReadInteger64(obj);
diff --git a/content/common/page_state_serialization.h b/content/common/page_state_serialization.h
index 24291ef..ef617a6e 100644
--- a/content/common/page_state_serialization.h
+++ b/content/common/page_state_serialization.h
@@ -23,7 +23,11 @@
   int64 file_start;
   int64 file_length;
   double file_modification_time;
+#ifdef USE_BLOB_UUIDS
+  std::string blob_uuid;
+#else
   GURL deprecated_blob_url;
+#endif
 
   ExplodedHttpBodyElement();
   ~ExplodedHttpBodyElement();
diff --git a/content/public/renderer/history_item_serialization.cc b/content/public/renderer/history_item_serialization.cc
index 14519d5..e7ff8f8 100644
--- a/content/public/renderer/history_item_serialization.cc
+++ b/content/public/renderer/history_item_serialization.cc
@@ -42,13 +42,17 @@
       output->file_modification_time = input.modificationTime;
       break;
     case WebHTTPBody::Element::TypeFileSystemURL:
-      output->filesystem_url = input.url;
+      output->filesystem_url = input.fileSystemURL;
       output->file_start = input.fileStart;
       output->file_length = input.fileLength;
       output->file_modification_time = input.modificationTime;
       break;
     case WebHTTPBody::Element::TypeBlob:
+#ifdef USE_BLOB_UUIDS
+      output->blob_uuid = input.blobUUID.utf8();
+#else
       output->deprecated_blob_url = input.blobURL;
+#endif
       break;
   }
 }
@@ -67,14 +71,18 @@
           element.file_modification_time);
       break;
     case WebHTTPBody::Element::TypeFileSystemURL:
-      http_body->appendURLRange(
+      http_body->appendFileSystemURLRange(
           element.filesystem_url,
           element.file_start,
           element.file_length,
           element.file_modification_time);
       break;
     case WebHTTPBody::Element::TypeBlob:
+#ifdef USE_BLOB_UUIDS
+      http_body->appendBlob(WebString::fromUTF8(element.blob_uuid));
+#else
       http_body->appendBlob(element.deprecated_blob_url);
+#endif
       break;
   }
 }
diff --git a/webkit/browser/blob/blob_url_request_job_factory.cc b/webkit/browser/blob/blob_url_request_job_factory.cc
index 71fad49..6f4f70f 100644
--- a/webkit/browser/blob/blob_url_request_job_factory.cc
+++ b/webkit/browser/blob/blob_url_request_job_factory.cc
@@ -7,6 +7,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/string_util.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_job_factory.h"
 #include "webkit/browser/blob/blob_data_handle.h"
@@ -77,6 +78,17 @@
   // The FeedbackExtensionAPI relies on this.
   scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(
       context_->LookupUuidFromDeprecatedURL(request->url()));
+  if (handle)
+    return handle->data();
+
+  // Support looking up based on uuid, the FeedbackExtensionAPI relies on this.
+  // TODO(michaeln): Replace this use case and others like it with a BlobReader
+  // impl that does not depend on urlfetching to perform this function.
+  const std::string kPrefix("blob:uuid/");
+  if (!StartsWithASCII(request->url().spec(), kPrefix, true))
+    return NULL;
+  std::string uuid = request->url().spec().substr(kPrefix.length());
+  handle = context_->GetBlobDataFromUUID(uuid);
   return handle.get() ? handle->data() : NULL;
 }
 
diff --git a/webkit/child/weburlloader_impl.cc b/webkit/child/weburlloader_impl.cc
index 8de8752..320cbbe 100644
--- a/webkit/child/weburlloader_impl.cc
+++ b/webkit/child/weburlloader_impl.cc
@@ -423,17 +423,21 @@
           }
           break;
         case WebHTTPBody::Element::TypeFileSystemURL: {
-          GURL url = GURL(element.url);
-          DCHECK(url.SchemeIsFileSystem());
+          GURL file_system_url = element.fileSystemURL;
+          DCHECK(file_system_url.SchemeIsFileSystem());
           request_body->AppendFileSystemFileRange(
-              url,
+              file_system_url,
               static_cast<uint64>(element.fileStart),
               static_cast<uint64>(element.fileLength),
               base::Time::FromDoubleT(element.modificationTime));
           break;
         }
         case WebHTTPBody::Element::TypeBlob:
+#ifdef USE_BLOB_UUIDS
+          request_body->AppendBlob(element.blobUUID.utf8());
+#else
           request_body->AppendBlobDeprecated(GURL(element.blobURL));
+#endif
           break;
         default:
           NOTREACHED();