| Index: tools/skiaserve/skiaserve.cpp
 | 
| diff --git a/tools/skiaserve/skiaserve.cpp b/tools/skiaserve/skiaserve.cpp
 | 
| index effd28973c226bd007a98b7e185b63aa04001d58..9252da85dcba497504ca8c52b43abf760a32cba9 100644
 | 
| --- a/tools/skiaserve/skiaserve.cpp
 | 
| +++ b/tools/skiaserve/skiaserve.cpp
 | 
| @@ -9,20 +9,11 @@
 | 
|  #include "GrContextFactory.h"
 | 
|  #include "SkCanvas.h"
 | 
|  #include "SkCommandLineFlags.h"
 | 
| -#include "SkOSFile.h"
 | 
| -#include <SkPicture.h>
 | 
| +#include "SkPicture.h"
 | 
|  #include "SkStream.h"
 | 
|  #include "SkSurface.h"
 | 
|  
 | 
| -// temporary junk
 | 
| -#include "SkGradientShader.h"
 | 
| -
 | 
| -#include <stdio.h>
 | 
| -#include <sys/types.h>
 | 
| -#include <sys/select.h>
 | 
| -#include <sys/stat.h>
 | 
|  #include <sys/socket.h>
 | 
| -#include <fcntl.h>
 | 
|  #include <microhttpd.h>
 | 
|  
 | 
|  // To get image decoders linked in we have to do the below magic
 | 
| @@ -42,7 +33,7 @@ static const int kImageWidth = 1920;
 | 
|  static const int kImageHeight = 1080;
 | 
|  
 | 
|  // TODO factor this out into functions, also handle CPU path
 | 
| -SkData* setupAndDrawToCanvas(const char* path, SkString* error) {
 | 
| +SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) {
 | 
|      GrContextOptions grContextOpts;
 | 
|      SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts));
 | 
|  
 | 
| @@ -64,15 +55,9 @@ SkData* setupAndDrawToCanvas(const char* path, SkString* error) {
 | 
|      gl->makeCurrent();
 | 
|  
 | 
|      // draw
 | 
| -    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
 | 
| -    if (stream.get() == nullptr) {
 | 
| -        error->appendf("Could not read %s.\n", path);
 | 
| -        return nullptr;
 | 
| -    }
 | 
| -
 | 
| -    SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get()));
 | 
| +    SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
 | 
|      if (pic.get() == nullptr) {
 | 
| -        error->appendf("Could not read %s as an SkPicture.\n", path);
 | 
| +        error->appendf("Could not create picture from stream.\n");
 | 
|          return nullptr;
 | 
|      }
 | 
|  
 | 
| @@ -95,7 +80,6 @@ SkData* setupAndDrawToCanvas(const char* path, SkString* error) {
 | 
|      }
 | 
|      return data;
 | 
|  }
 | 
| -
 | 
|  // TODO move to template file
 | 
|  SkString generateTemplate(SkString source) {
 | 
|      SkString debuggerTemplate;
 | 
| @@ -119,53 +103,127 @@ SkString generateTemplate(SkString source) {
 | 
|  
 | 
|  }
 | 
|  
 | 
| +struct UploadContext {
 | 
| +    SkDynamicMemoryWStream stream;
 | 
| +    MHD_PostProcessor* pp;
 | 
| +    MHD_Connection* connection;
 | 
| +};
 | 
| +
 | 
| +struct Request {
 | 
| +    Request() : fUploadContext(nullptr) {}
 | 
| +    UploadContext* fUploadContext;
 | 
| +    SkAutoTUnref<SkData> fPNG;
 | 
| +};
 | 
| +
 | 
| +static const size_t kBufferSize = 1024;
 | 
| +
 | 
| +static int process_upload_data(void* cls, enum MHD_ValueKind kind,
 | 
| +                               const char* key, const char* filename,
 | 
| +                               const char* content_type, const char* transfer_encoding,
 | 
| +                               const char* data, uint64_t off, size_t size) {
 | 
| +    struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls);
 | 
| +
 | 
| +    if (0 != size) {
 | 
| +        uc->stream.write(data, size);
 | 
| +    }
 | 
| +    return MHD_YES;
 | 
| +}
 | 
| +
 | 
|  int answer_to_connection(void* cls, struct MHD_Connection* connection,
 | 
|                           const char* url, const char* method, const char* version,
 | 
|                           const char* upload_data, size_t* upload_data_size,
 | 
|                           void** con_cls) {
 | 
| -    printf ("New %s request for %s using version %s\n", method, url, version);
 | 
| -
 | 
| -    struct MHD_Response* response;
 | 
| -
 | 
| -    // serve html to root
 | 
| -    // TODO better url handling
 | 
| -    int ret;
 | 
| -    if (0 == strcmp("/", url)) {
 | 
| +    SkDebugf("New %s request for %s using version %s\n", method, url, version);
 | 
| +
 | 
| +    Request* request = reinterpret_cast<Request*>(cls);
 | 
| +
 | 
| +    MHD_Response* response;
 | 
| +    int ret = MHD_NO;
 | 
| +
 | 
| +    // TODO url handlers
 | 
| +    // handle uploads
 | 
| +    if (0 == strcmp(method, MHD_HTTP_METHOD_POST) &&
 | 
| +        0 == strcmp(url, "/new")) {
 | 
| +        UploadContext* uc =  request->fUploadContext;
 | 
| +
 | 
| +        // New connection
 | 
| +        if (!uc) {
 | 
| +            // TODO make this a method on request
 | 
| +            uc = new UploadContext;
 | 
| +            uc->connection = connection;
 | 
| +            uc->pp = MHD_create_post_processor(connection, kBufferSize, &process_upload_data, uc);
 | 
| +            SkASSERT(uc->pp);
 | 
| +
 | 
| +            request->fUploadContext = uc;
 | 
| +            return MHD_YES;
 | 
| +        }
 | 
| +
 | 
| +        // in process upload
 | 
| +        if (0 != *upload_data_size) {
 | 
| +            SkASSERT(uc->pp);
 | 
| +            MHD_post_process(uc->pp, upload_data, *upload_data_size);
 | 
| +            *upload_data_size = 0;
 | 
| +            return MHD_YES;
 | 
| +        }
 | 
| +
 | 
| +        // end of upload
 | 
| +        MHD_destroy_post_processor(uc->pp);
 | 
| +        uc->pp = nullptr;
 | 
| +
 | 
| +        // TODO response
 | 
| +        SkString error;
 | 
| +        SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error);
 | 
| +        if (!data) {
 | 
| +            // TODO send error
 | 
| +            return MHD_YES;
 | 
| +        }
 | 
| +
 | 
| +        request->fPNG.reset(data);
 | 
| +        // TODO Hack
 | 
|          SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
 | 
|  
 | 
|          response = MHD_create_response_from_buffer(debuggerTemplate.size(),
 | 
| -                                                   (void*)const_cast<char*>(debuggerTemplate.c_str()),
 | 
| +                                                   (void*) const_cast<char*>(debuggerTemplate.c_str()),
 | 
|                                                     MHD_RESPMEM_MUST_COPY);
 | 
| +
 | 
|          ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
 | 
|          MHD_destroy_response(response);
 | 
| -        return MHD_YES;
 | 
| -    }
 | 
| -
 | 
| -    // otherwise serve an image
 | 
| -    // TODO take from post
 | 
| -    SkString resourceName;
 | 
| -    resourceName.appendf("%s/%s.skp", FLAGS_dir[0], FLAGS_name[0]);
 | 
| -    SkDebugf("Loading skp: %s\n", resourceName.c_str());
 | 
| -
 | 
| -    SkString error;
 | 
| -    SkAutoTUnref<SkData> data(setupAndDrawToCanvas(resourceName.c_str(), &error));
 | 
| -    if (!data) {
 | 
| -        // TODO send error
 | 
| -        return MHD_YES;
 | 
| +    } else if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) {
 | 
| +        if (0 == strcmp(url, "/")) {
 | 
| +            SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
 | 
| +
 | 
| +            response = MHD_create_response_from_buffer(debuggerTemplate.size(),
 | 
| +                                                       (void*) const_cast<char*>(debuggerTemplate.c_str()),
 | 
| +                                                       MHD_RESPMEM_MUST_COPY);
 | 
| +
 | 
| +            ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
 | 
| +            MHD_destroy_response(response);
 | 
| +        } else if (0 == strcmp(url, "/img")) {
 | 
| +            if (request->fPNG.get()) {
 | 
| +                SkData* data = request->fPNG.get();
 | 
| +                response = MHD_create_response_from_buffer(data->size(),
 | 
| +                                                           const_cast<void*>(data->data()),
 | 
| +                                                           MHD_RESPMEM_MUST_COPY);
 | 
| +                MHD_add_response_header(response, "Content-Type", "image/png");
 | 
| +
 | 
| +                ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
 | 
| +                MHD_destroy_response(response);
 | 
| +            }
 | 
| +        }
 | 
| +    } else {
 | 
| +        SkFAIL("whoops, need proper error handling");
 | 
| +        return MHD_NO;
 | 
|      }
 | 
|  
 | 
| -    response = MHD_create_response_from_buffer(data->size(), const_cast<void*>(data->data()),
 | 
| -                                               MHD_RESPMEM_MUST_COPY);
 | 
| -    MHD_add_response_header(response, "Content-Type", "image/png");
 | 
| -    ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
 | 
| -    MHD_destroy_response(response);
 | 
|      return ret;
 | 
|  }
 | 
|  
 | 
|  int skiaserve_main() {
 | 
| +    Request request; // This simple server has one request
 | 
|      struct MHD_Daemon* daemon;
 | 
| -    daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
 | 
| -                              &answer_to_connection, NULL, MHD_OPTION_END);
 | 
| +    daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, nullptr, nullptr,
 | 
| +                              &answer_to_connection, &request,
 | 
| +                              MHD_OPTION_END);
 | 
|      if (NULL == daemon) {
 | 
|          return 1;
 | 
|      }
 | 
| 
 |