Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrCaps.h" | 8 #include "GrCaps.h" |
| 9 #include "GrContextFactory.h" | 9 #include "GrContextFactory.h" |
| 10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
| 11 #include "SkCommandLineFlags.h" | 11 #include "SkCommandLineFlags.h" |
| 12 #include "SkDebugCanvas.h" | |
| 12 #include "SkJSONCanvas.h" | 13 #include "SkJSONCanvas.h" |
| 13 #include "SkPicture.h" | 14 #include "SkPicture.h" |
| 14 #include "SkStream.h" | 15 #include "SkStream.h" |
| 15 #include "SkSurface.h" | 16 #include "SkSurface.h" |
| 16 | 17 |
| 17 #include <sys/socket.h> | 18 #include <sys/socket.h> |
| 18 #include <microhttpd.h> | 19 #include <microhttpd.h> |
| 19 | 20 |
| 20 // To get image decoders linked in we have to do the below magic | 21 // To get image decoders linked in we have to do the below magic |
| 21 #include "SkForceLinking.h" | 22 #include "SkForceLinking.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 | 55 |
| 55 struct UploadContext { | 56 struct UploadContext { |
| 56 SkDynamicMemoryWStream fStream; | 57 SkDynamicMemoryWStream fStream; |
| 57 MHD_PostProcessor* fPostProcessor; | 58 MHD_PostProcessor* fPostProcessor; |
| 58 MHD_Connection* connection; | 59 MHD_Connection* connection; |
| 59 }; | 60 }; |
| 60 | 61 |
| 61 struct Request { | 62 struct Request { |
| 62 Request() : fUploadContext(nullptr) {} | 63 Request() : fUploadContext(nullptr) {} |
| 63 UploadContext* fUploadContext; | 64 UploadContext* fUploadContext; |
| 64 SkAutoTUnref<SkData> fPNG; | |
| 65 SkAutoTUnref<SkPicture> fPicture; | 65 SkAutoTUnref<SkPicture> fPicture; |
| 66 SkAutoTUnref<SkDebugCanvas> fDebugCanvas; | |
| 66 }; | 67 }; |
| 67 | 68 |
| 68 // TODO factor this out into functions, also handle CPU path | 69 // TODO factor this out into functions, also handle CPU path |
| 69 bool setupAndDrawToCanvas(Request* request, SkString* error) { | 70 SkSurface* setupSurface(GrContextFactory* factory) { |
| 70 GrContextOptions grContextOpts; | |
| 71 SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts)) ; | |
| 72 | |
| 73 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, | 71 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, |
| 74 GrContextFactory::kNone_GLContextOptions); | 72 GrContextFactory::kNone_GLContextOptions); |
| 75 int maxRTSize = context->caps()->maxRenderTargetSize(); | 73 int maxRTSize = context->caps()->maxRenderTargetSize(); |
| 76 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), | 74 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), |
| 77 SkTMin(kImageHeight, maxRTSize), | 75 SkTMin(kImageHeight, maxRTSize), |
| 78 kN32_SkColorType, kPremul_SkAlphaType); | 76 kN32_SkColorType, kPremul_SkAlphaType); |
| 79 uint32_t flags = 0; | 77 uint32_t flags = 0; |
| 80 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | 78 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
| 81 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, | 79 SkSurface* surface = SkSurface::NewRenderTarget(context, SkSurface::kNo_Budg eted, info, 0, |
| 82 SkSurface::kNo_Bu dgeted, info, | 80 &props); |
| 83 0, &props)); | 81 SkASSERT(surface); |
| 84 SkASSERT(surface.get()); | |
| 85 | 82 |
| 86 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex tType, | 83 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex tType, |
| 87 GrContextFactory::kNone_GLContextO ptions).fGLContext; | 84 GrContextFactory::kNone_GLContextO ptions).fGLContext; |
| 88 gl->makeCurrent(); | 85 gl->makeCurrent(); |
| 86 return surface; | |
| 87 } | |
| 89 | 88 |
| 90 // draw | 89 SkData* writeCanvasToPng(SkCanvas* canvas) { |
| 91 request->fPicture.reset( | |
| 92 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachAsStr eam())); | |
| 93 if (!request->fPicture.get()) { | |
| 94 error->appendf("Could not create picture from stream.\n"); | |
| 95 return false; | |
| 96 } | |
| 97 | |
| 98 SkCanvas* canvas = surface->getCanvas(); | |
| 99 canvas->drawPicture(request->fPicture); | |
| 100 | |
| 101 // capture pixels | 90 // capture pixels |
| 102 SkBitmap bmp; | 91 SkBitmap bmp; |
| 103 bmp.setInfo(canvas->imageInfo()); | 92 bmp.setInfo(canvas->imageInfo()); |
| 104 if (!canvas->readPixels(&bmp, 0, 0)) { | 93 if (!canvas->readPixels(&bmp, 0, 0)) { |
| 105 error->appendf("Can't read canvas pixels.\n"); | 94 fprintf(stderr, "Can't read pixels\n"); |
| 106 return false; | 95 return nullptr; |
| 107 } | 96 } |
| 108 | 97 |
| 109 // write to png | 98 // write to png |
| 110 request->fPNG.reset(SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Typ e, 100)); | 99 SkData* png = SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 100 ); |
| 111 if (!request->fPNG) { | 100 if (!png) { |
| 112 error->appendf("Can't encode a PNG.\n"); | 101 fprintf(stderr, "Can't encode to png\n"); |
| 113 return false; | 102 return nullptr; |
| 114 } | 103 } |
| 115 return true; | 104 return png; |
| 105 } | |
| 106 | |
| 107 SkData* setupAndDrawToCanvasReturnPng(SkDebugCanvas* debugCanvas, int n) { | |
| 108 GrContextOptions grContextOpts; | |
| 109 SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts)) ; | |
| 110 SkAutoTUnref<SkSurface> surface(setupSurface(factory.get())); | |
| 111 | |
| 112 SkASSERT(debugCanvas); | |
| 113 SkCanvas* canvas = surface->getCanvas(); | |
| 114 debugCanvas->drawTo(canvas, n); | |
| 115 return writeCanvasToPng(canvas); | |
| 116 } | 116 } |
| 117 | 117 |
| 118 static const size_t kBufferSize = 1024; | 118 static const size_t kBufferSize = 1024; |
| 119 | 119 |
| 120 static int process_upload_data(void* cls, enum MHD_ValueKind kind, | 120 static int process_upload_data(void* cls, enum MHD_ValueKind kind, |
| 121 const char* key, const char* filename, | 121 const char* key, const char* filename, |
| 122 const char* content_type, const char* transfer_en coding, | 122 const char* content_type, const char* transfer_en coding, |
| 123 const char* data, uint64_t off, size_t size) { | 123 const char* data, uint64_t off, size_t size) { |
| 124 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); | 124 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); |
| 125 | 125 |
| 126 if (0 != size) { | 126 if (0 != size) { |
| 127 uc->fStream.write(data, size); | 127 uc->fStream.write(data, size); |
| 128 } | 128 } |
| 129 return MHD_YES; | 129 return MHD_YES; |
| 130 } | 130 } |
| 131 | 131 |
| 132 static int SendData(MHD_Connection* connection, const SkData* data, const char* type) { | 132 static int SendData(MHD_Connection* connection, const SkData* data, const char* type) { |
| 133 MHD_Response* response = MHD_create_response_from_buffer(data->size(), | 133 MHD_Response* response = MHD_create_response_from_buffer(data->size(), |
| 134 const_cast<void*>(d ata->data()), | 134 const_cast<void*>(d ata->data()), |
| 135 MHD_RESPMEM_MUST_CO PY); | 135 MHD_RESPMEM_MUST_CO PY); |
| 136 MHD_add_response_header(response, "Content-Type", type); | 136 MHD_add_response_header(response, "Content-Type", type); |
| 137 | 137 |
| 138 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); | 138 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
| 139 MHD_destroy_response(response); | 139 MHD_destroy_response(response); |
| 140 return ret; | 140 return ret; |
| 141 } | 141 } |
| 142 | 142 |
| 143 static int SendJSON(MHD_Connection* connection, SkPicture* picture) { | 143 static int SendJSON(MHD_Connection* connection, SkDebugCanvas* debugCanvas, int n) { |
| 144 SkDynamicMemoryWStream stream; | 144 SkDynamicMemoryWStream stream; |
| 145 SkAutoTUnref<SkJSONCanvas> jsonCanvas(new SkJSONCanvas(kImageWidth, kImageHe ight, stream)); | 145 SkAutoTUnref<SkJSONCanvas> jsonCanvas(new SkJSONCanvas(kImageWidth, kImageHe ight, stream)); |
| 146 jsonCanvas->drawPicture(picture); | 146 debugCanvas->drawTo(jsonCanvas, n); |
| 147 jsonCanvas->finish(); | 147 jsonCanvas->finish(); |
| 148 | 148 |
| 149 SkAutoTUnref<SkData> data(stream.copyToData()); | 149 SkAutoTUnref<SkData> data(stream.copyToData()); |
| 150 return SendData(connection, data, "application/json"); | 150 return SendData(connection, data, "application/json"); |
| 151 } | 151 } |
| 152 | 152 |
| 153 static int SendTemplate(MHD_Connection* connection, bool redirect = false, | 153 static int SendTemplate(MHD_Connection* connection, bool redirect = false, |
| 154 const char* redirectUrl = nullptr) { | 154 const char* redirectUrl = nullptr) { |
| 155 SkString debuggerTemplate = generateTemplate(SkString(FLAGS_source[0])); | 155 SkString debuggerTemplate = generateTemplate(SkString(FLAGS_source[0])); |
| 156 | 156 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 170 int ret = MHD_queue_response(connection, status, response); | 170 int ret = MHD_queue_response(connection, status, response); |
| 171 MHD_destroy_response(response); | 171 MHD_destroy_response(response); |
| 172 return ret; | 172 return ret; |
| 173 } | 173 } |
| 174 | 174 |
| 175 class UrlHandler { | 175 class UrlHandler { |
| 176 public: | 176 public: |
| 177 virtual ~UrlHandler() {} | 177 virtual ~UrlHandler() {} |
| 178 virtual bool canHandle(const char* method, const char* url) = 0; | 178 virtual bool canHandle(const char* method, const char* url) = 0; |
| 179 virtual int handle(Request* request, MHD_Connection* connection, | 179 virtual int handle(Request* request, MHD_Connection* connection, |
| 180 const char* url, const char* method, | |
| 180 const char* upload_data, size_t* upload_data_size) = 0; | 181 const char* upload_data, size_t* upload_data_size) = 0; |
| 181 }; | 182 }; |
| 182 | 183 |
| 183 class InfoHandler : public UrlHandler { | 184 class InfoHandler : public UrlHandler { |
| 184 public: | 185 public: |
| 185 bool canHandle(const char* method, const char* url) override { | 186 bool canHandle(const char* method, const char* url) override { |
| 186 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && | 187 const char* kBasePath = "/cmd"; |
| 187 0 == strcmp(url, "/cmd"); | 188 return 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
| 188 } | 189 } |
| 189 | 190 |
| 190 int handle(Request* request, MHD_Connection* connection, | 191 int handle(Request* request, MHD_Connection* connection, |
| 192 const char* url, const char* method, | |
| 191 const char* upload_data, size_t* upload_data_size) override { | 193 const char* upload_data, size_t* upload_data_size) override { |
| 192 if (request->fPicture.get()) { | 194 SkTArray<SkString> commands; |
| 193 return SendJSON(connection, request->fPicture); | 195 SkStrSplit(url, "/", &commands); |
| 196 | |
| 197 if (!request->fPicture.get() || commands.count() > 3) { | |
| 198 return MHD_NO; | |
| 194 } | 199 } |
| 200 | |
| 201 // /cmd or /cmd/N or /cmd/N/[0|1] | |
| 202 if (commands.count() == 1 && 0 == strcmp(method, MHD_HTTP_METHOD_GET)) { | |
| 203 int n = request->fDebugCanvas->getSize() - 1; | |
| 204 return SendJSON(connection, request->fDebugCanvas, n); | |
| 205 } | |
| 206 | |
| 207 // /cmd/N, for now only delete supported | |
| 208 if (commands.count() == 2 && 0 == strcmp(method, MHD_HTTP_METHOD_DELETE) ) { | |
| 209 int n; | |
| 210 sscanf(commands[1].c_str(), "%d", &n); | |
| 211 request->fDebugCanvas->deleteDrawCommandAt(n); | |
| 212 return MHD_YES; | |
| 213 } | |
| 214 | |
| 215 // /cmd/N/[0|1] | |
| 216 if (commands.count() == 3 && 0 == strcmp(method, MHD_HTTP_METHOD_POST)) { | |
| 217 int n, toggle; | |
| 218 sscanf(commands[1].c_str(), "%d", &n); | |
| 219 sscanf(commands[2].c_str(), "%d", &toggle); | |
| 220 request->fDebugCanvas->toggleCommand(n, toggle); | |
| 221 return MHD_YES; | |
| 222 } | |
| 223 | |
| 195 return MHD_NO; | 224 return MHD_NO; |
| 196 } | 225 } |
| 197 }; | 226 }; |
| 198 | 227 |
| 199 class ImgHandler : public UrlHandler { | 228 class ImgHandler : public UrlHandler { |
| 200 public: | 229 public: |
| 201 bool canHandle(const char* method, const char* url) override { | 230 bool canHandle(const char* method, const char* url) override { |
| 202 static const char* kBasePath = "/img"; | 231 static const char* kBasePath = "/img"; |
| 203 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && | 232 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 204 0 == strncmp(url, kBasePath, strlen(kBasePath)); | 233 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
| 205 } | 234 } |
| 206 | 235 |
| 207 int handle(Request* request, MHD_Connection* connection, | 236 int handle(Request* request, MHD_Connection* connection, |
| 237 const char* url, const char* method, | |
| 208 const char* upload_data, size_t* upload_data_size) override { | 238 const char* upload_data, size_t* upload_data_size) override { |
| 209 if (request->fPNG.get()) { | 239 SkTArray<SkString> commands; |
| 210 SkData* data = request->fPNG.get(); | 240 SkStrSplit(url, "/", &commands); |
|
jcgregorio
2016/02/02 18:08:13
Need to split off the trailing ?blahblahblah first
| |
| 211 return SendData(connection, data, "image/png"); | 241 |
| 242 if (!request->fPicture.get() || commands.count() > 2) { | |
| 243 return MHD_NO; | |
| 212 } | 244 } |
| 213 | 245 |
| 214 return MHD_NO; | 246 int n; |
| 247 // /img or /img/N | |
| 248 if (commands.count() == 1) { | |
| 249 n = request->fDebugCanvas->getSize() - 1; | |
| 250 } else { | |
| 251 sscanf(commands[1].c_str(), "%d", &n); | |
| 252 } | |
| 253 | |
| 254 SkAutoTUnref<SkData> data(setupAndDrawToCanvasReturnPng(request->fDebugC anvas, n)); | |
| 255 return SendData(connection, data, "image/png"); | |
| 215 } | 256 } |
| 216 }; | 257 }; |
| 217 | 258 |
| 218 class PostHandler : public UrlHandler { | 259 class PostHandler : public UrlHandler { |
| 219 public: | 260 public: |
| 220 bool canHandle(const char* method, const char* url) override { | 261 bool canHandle(const char* method, const char* url) override { |
| 221 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && | 262 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
| 222 0 == strcmp(url, "/new"); | 263 0 == strcmp(url, "/new"); |
| 223 } | 264 } |
| 224 | 265 |
| 225 int handle(Request* request, MHD_Connection* connection, | 266 int handle(Request* request, MHD_Connection* connection, |
| 267 const char* url, const char* method, | |
| 226 const char* upload_data, size_t* upload_data_size) override { | 268 const char* upload_data, size_t* upload_data_size) override { |
| 227 UploadContext* uc = request->fUploadContext; | 269 UploadContext* uc = request->fUploadContext; |
| 228 | 270 |
| 229 // New connection | 271 // New connection |
| 230 if (!uc) { | 272 if (!uc) { |
| 231 // TODO make this a method on request | 273 // TODO make this a method on request |
| 232 uc = new UploadContext; | 274 uc = new UploadContext; |
| 233 uc->connection = connection; | 275 uc->connection = connection; |
| 234 uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSi ze, | 276 uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSi ze, |
| 235 &process_upload_data, uc); | 277 &process_upload_data, uc); |
| 236 SkASSERT(uc->fPostProcessor); | 278 SkASSERT(uc->fPostProcessor); |
| 237 | 279 |
| 238 request->fUploadContext = uc; | 280 request->fUploadContext = uc; |
| 239 return MHD_YES; | 281 return MHD_YES; |
| 240 } | 282 } |
| 241 | 283 |
| 242 // in process upload | 284 // in process upload |
| 243 if (0 != *upload_data_size) { | 285 if (0 != *upload_data_size) { |
| 244 SkASSERT(uc->fPostProcessor); | 286 SkASSERT(uc->fPostProcessor); |
| 245 MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size) ; | 287 MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size) ; |
| 246 *upload_data_size = 0; | 288 *upload_data_size = 0; |
| 247 return MHD_YES; | 289 return MHD_YES; |
| 248 } | 290 } |
| 249 | 291 |
| 250 // end of upload | 292 // end of upload |
| 251 MHD_destroy_post_processor(uc->fPostProcessor); | 293 MHD_destroy_post_processor(uc->fPostProcessor); |
| 252 uc->fPostProcessor = nullptr; | 294 uc->fPostProcessor = nullptr; |
| 253 | 295 |
| 254 // TODO response | 296 // parse picture from stream |
| 255 SkString error; | 297 request->fPicture.reset( |
| 256 if (!setupAndDrawToCanvas(request, &error)) { | 298 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachA sStream())); |
| 257 // TODO send error | 299 if (!request->fPicture.get()) { |
| 258 return MHD_YES; | 300 fprintf(stderr, "Could not create picture from stream.\n"); |
| 301 return MHD_NO; | |
| 259 } | 302 } |
| 260 | 303 |
| 304 // pour picture into debug canvas | |
| 305 request->fDebugCanvas.reset(new SkDebugCanvas(kImageWidth, kImageHeight) ); | |
| 306 request->fDebugCanvas->drawPicture(request->fPicture); | |
| 307 | |
| 261 // clear upload context | 308 // clear upload context |
| 262 delete request->fUploadContext; | 309 delete request->fUploadContext; |
| 263 request->fUploadContext = nullptr; | 310 request->fUploadContext = nullptr; |
| 264 | 311 |
| 265 return SendTemplate(connection, true, "/"); | 312 return SendTemplate(connection, true, "/"); |
| 266 } | 313 } |
| 267 }; | 314 }; |
| 268 | 315 |
| 269 class RootHandler : public UrlHandler { | 316 class RootHandler : public UrlHandler { |
| 270 public: | 317 public: |
| 271 bool canHandle(const char* method, const char* url) override { | 318 bool canHandle(const char* method, const char* url) override { |
| 272 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && | 319 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 273 0 == strcmp(url, "/"); | 320 0 == strcmp(url, "/"); |
| 274 } | 321 } |
| 275 | 322 |
| 276 int handle(Request* request, MHD_Connection* connection, | 323 int handle(Request* request, MHD_Connection* connection, |
| 324 const char* url, const char* method, | |
| 277 const char* upload_data, size_t* upload_data_size) override { | 325 const char* upload_data, size_t* upload_data_size) override { |
| 278 return SendTemplate(connection); | 326 return SendTemplate(connection); |
| 279 } | 327 } |
| 280 }; | 328 }; |
| 281 | 329 |
| 282 class UrlManager { | 330 class UrlManager { |
| 283 public: | 331 public: |
| 284 UrlManager() { | 332 UrlManager() { |
| 285 // Register handlers | 333 // Register handlers |
| 286 fHandlers.push_back(new RootHandler); | 334 fHandlers.push_back(new RootHandler); |
| 287 fHandlers.push_back(new PostHandler); | 335 fHandlers.push_back(new PostHandler); |
| 288 fHandlers.push_back(new ImgHandler); | 336 fHandlers.push_back(new ImgHandler); |
| 289 fHandlers.push_back(new InfoHandler); | 337 fHandlers.push_back(new InfoHandler); |
| 290 } | 338 } |
| 291 | 339 |
| 292 ~UrlManager() { | 340 ~UrlManager() { |
| 293 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } | 341 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } |
| 294 } | 342 } |
| 295 | 343 |
| 296 // This is clearly not efficient for a large number of urls and handlers | 344 // This is clearly not efficient for a large number of urls and handlers |
| 297 int invoke(Request* request, MHD_Connection* connection, const char* url, co nst char* method, | 345 int invoke(Request* request, MHD_Connection* connection, const char* url, co nst char* method, |
| 298 const char* upload_data, size_t* upload_data_size) const { | 346 const char* upload_data, size_t* upload_data_size) const { |
| 299 for (int i = 0; i < fHandlers.count(); i++) { | 347 for (int i = 0; i < fHandlers.count(); i++) { |
| 300 if (fHandlers[i]->canHandle(method, url)) { | 348 if (fHandlers[i]->canHandle(method, url)) { |
| 301 return fHandlers[i]->handle(request, connection, upload_data, up load_data_size); | 349 return fHandlers[i]->handle(request, connection, url, method, up load_data, |
| 350 upload_data_size); | |
| 302 } | 351 } |
| 303 } | 352 } |
| 304 return MHD_NO; | 353 return MHD_NO; |
| 305 } | 354 } |
| 306 | 355 |
| 307 private: | 356 private: |
| 308 SkTArray<UrlHandler*> fHandlers; | 357 SkTArray<UrlHandler*> fHandlers; |
| 309 }; | 358 }; |
| 310 | 359 |
| 311 const UrlManager kUrlManager; | 360 const UrlManager kUrlManager; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 340 MHD_stop_daemon(daemon); | 389 MHD_stop_daemon(daemon); |
| 341 return 0; | 390 return 0; |
| 342 } | 391 } |
| 343 | 392 |
| 344 #if !defined SK_BUILD_FOR_IOS | 393 #if !defined SK_BUILD_FOR_IOS |
| 345 int main(int argc, char** argv) { | 394 int main(int argc, char** argv) { |
| 346 SkCommandLineFlags::Parse(argc, argv); | 395 SkCommandLineFlags::Parse(argc, argv); |
| 347 return skiaserve_main(); | 396 return skiaserve_main(); |
| 348 } | 397 } |
| 349 #endif | 398 #endif |
| OLD | NEW |