From 8024f6a80484dfa0f485f076adf77dffb0f01347 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 15:12:11 -0500 Subject: [PATCH 1/9] Fixed: Move CPURLRequest methods to @accessors This commit changes the simple getters/setters from CPURLRequest to use @accessors. --- Foundation/CPURLRequest.j | 59 ++++----------------------------------- 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/Foundation/CPURLRequest.j b/Foundation/CPURLRequest.j index 703c81bcc..b643264a3 100644 --- a/Foundation/CPURLRequest.j +++ b/Foundation/CPURLRequest.j @@ -35,12 +35,13 @@ */ @implementation CPURLRequest : CPObject { - CPURL _URL; + CPURL _URL @accessors(property=URL); // FIXME: this should be CPData - CPString _HTTPBody; - CPString _HTTPMethod; - CPDictionary _HTTPHeaderFields; + CPString _HTTPBody @accessors(property=HTTPBody); + CPString _HTTPMethod @accessors(property=HTTPMethod); + + CPDictionary _HTTPHeaderFields @accessors(readonly, getter=allHTTPHeaderFields); } /*! @@ -87,14 +88,6 @@ return self; } -/*! - Returns the request URL -*/ -- (CPURL)URL -{ - return _URL; -} - /*! Sets the URL for this request. @param aURL the new URL @@ -105,48 +98,6 @@ _URL = new CFURL(aURL); } -/*! - Sets the HTTP body for this request - @param anHTTPBody the new HTTP body -*/ -- (void)setHTTPBody:(CPString)anHTTPBody -{ - _HTTPBody = anHTTPBody; -} - -/*! - Returns the request's http body. -*/ -- (CPString)HTTPBody -{ - return _HTTPBody; -} - -/*! - Sets the request's http method. - @param anHTPPMethod the new http method -*/ -- (void)setHTTPMethod:(CPString)anHTTPMethod -{ - _HTTPMethod = anHTTPMethod; -} - -/*! - Returns the request's http method -*/ -- (CPString)HTTPMethod -{ - return _HTTPMethod; -} - -/*! - Returns a dictionary of the http header fields -*/ -- (CPDictionary)allHTTPHeaderFields -{ - return _HTTPHeaderFields; -} - /*! Returns the value for the specified header field. @param aField the header field to obtain a value for From d1917db47e9d5a58501cfcee4b4207e201d37306 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 15:29:52 -0500 Subject: [PATCH 2/9] Fixed: Reworked withCredentials for XMLHTTPRequests Previously, the withCredentials parameter was accessed primarily through the CPURLConnection, which gave limited access to changing the request before it was sent off. This commit removes withCredentials from CPURLConnection and places it on CPURLRequest so that it may be more easily modified prior to sending the request. This also simplifies the logic in CPURLConnection for creating and establishing connections with credentials. In this commit, all CFHTTPRequests are assumed to not use withCredentials unless they are explicitly set. Setting [aURLRequest withCredentials] will set the withCredentials property on the underlying XMLHTTPRequest prior to the connection being opened. --- Foundation/CPURLConnection.j | 36 ++++-------------------------------- Foundation/CPURLRequest.j | 1 + Objective-J/CFHTTPRequest.js | 5 ++++- 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/Foundation/CPURLConnection.j b/Foundation/CPURLConnection.j index 88a1afbf8..7c4cfd81e 100644 --- a/Foundation/CPURLConnection.j +++ b/Foundation/CPURLConnection.j @@ -81,8 +81,6 @@ var CPURLConnectionDelegate = nil; BOOL _isCanceled; BOOL _isLocalFileConnection; - BOOL _withCredentials @accessors(property=withCredentials); - HTTPRequest _HTTPRequest; } @@ -99,25 +97,12 @@ var CPURLConnectionDelegate = nil; @return the data at the URL or \c nil if there was an error */ + (CPData)sendSynchronousRequest:(CPURLRequest)aRequest returningResponse:(/*{*/CPURLResponse/*}*/)aURLResponse -{ - var cfHTTPRequest = new CFHTTPRequest(); - - return [CPURLConnection _sendSynchronousRequest:aRequest returningResponse:aURLResponse withCFHTTPRequest:cfHTTPRequest]; -} - -+ (CPData)sendSynchronousRequest:(CPURLRequest)aRequest returningResponse:(/*{*/CPURLResponse/*}*/)aURLResponse withCredentials:(BOOL)withCredentials -{ - var cfHTTPRequest = new CFHTTPRequest(); - - cfHTTPRequest.setWithCredentials(withCredentials); - - return [CPURLConnection _sendSynchronousRequest:aRequest returningResponse:aURLResponse withCFHTTPRequest:cfHTTPRequest]; -} - -+ (CPData)_sendSynchronousRequest:(CPURLRequest)aRequest returningResponse:(/*{*/CPURLResponse/*}*/)aURLResponse withCFHTTPRequest:(CFHTTPRequest)aCFHTTPRequest { try { + var aCFHTTPRequest = new CFHTTPRequest(); + aCFHTTPRequest.setWithCredentials([aRequest withCredentials]); + aCFHTTPRequest.open([aRequest HTTPMethod], [[aRequest URL] absoluteString], NO); var fields = [aRequest allHTTPHeaderFields], @@ -152,17 +137,6 @@ var CPURLConnectionDelegate = nil; return [[self alloc] initWithRequest:aRequest delegate:aDelegate]; } -//overloaded method that allows user to set _withCredentials -+ (CPURLConnection)connectionWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate withCredentials:(BOOL)withCredentials -{ - var connection = [[self alloc] initWithRequest:aRequest delegate:aDelegate startImmediately:NO]; - - [connection setWithCredentials:withCredentials]; - [connection start]; - - return connection; -} - /* Default class initializer. Use one of the class methods instead. @param aRequest contains the URL to contact @@ -179,7 +153,6 @@ var CPURLConnectionDelegate = nil; _request = aRequest; _delegate = aDelegate; _isCanceled = NO; - _withCredentials = NO; var URL = [_request URL], scheme = [URL scheme]; @@ -191,6 +164,7 @@ var CPURLConnectionDelegate = nil; (window.location.protocol === "file:" || window.location.protocol === "app:")); _HTTPRequest = new CFHTTPRequest(); + _HTTPRequest.setWithCredentials([aRequest withCredentials]); if (shouldStartImmediately) [self start]; @@ -219,8 +193,6 @@ var CPURLConnectionDelegate = nil; { _isCanceled = NO; - _HTTPRequest.setWithCredentials(_withCredentials); - try { _HTTPRequest.open([_request HTTPMethod], [[_request URL] absoluteString], YES); diff --git a/Foundation/CPURLRequest.j b/Foundation/CPURLRequest.j index b643264a3..3b93b8d06 100644 --- a/Foundation/CPURLRequest.j +++ b/Foundation/CPURLRequest.j @@ -40,6 +40,7 @@ // FIXME: this should be CPData CPString _HTTPBody @accessors(property=HTTPBody); CPString _HTTPMethod @accessors(property=HTTPMethod); + BOOL _withCredentials @accessors(property=withCredentials); CPDictionary _HTTPHeaderFields @accessors(readonly, getter=allHTTPHeaderFields); } diff --git a/Objective-J/CFHTTPRequest.js b/Objective-J/CFHTTPRequest.js index 6186dc80f..37bdf61e8 100644 --- a/Objective-J/CFHTTPRequest.js +++ b/Objective-J/CFHTTPRequest.js @@ -103,6 +103,9 @@ GLOBAL(CFHTTPRequest) = function() this._eventDispatcher = new EventDispatcher(this); this._nativeRequest = new NativeRequest(); + // by default, all requests will assume that credentials should not be sent. + this._nativeRequest.withCredentials = false; + var self = this; this._stateChangeHandler = function() { @@ -279,7 +282,7 @@ CFHTTPRequest.prototype.setWithCredentials = function(/*Boolean*/ willSendWithCr this._nativeRequest.withCredentials = willSendWithCredentials; }; -CFHTTPRequest.prototype.getWithCredentials = function() +CFHTTPRequest.prototype.withCredentials = function() { return this._nativeRequest.withCredentials; }; From cd2e9e29d4c0b99c702c54c105ec7d1790dfe34a Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 16:37:34 -0500 Subject: [PATCH 3/9] Tests: Fixed tests for withCredentials --- Tests/Foundation/CPURLConnectionTest.j | 6 ------ Tests/Objective-J/CFHTTPRequestTest.j | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Tests/Foundation/CPURLConnectionTest.j b/Tests/Foundation/CPURLConnectionTest.j index 91df094d3..a7486abac 100644 --- a/Tests/Foundation/CPURLConnectionTest.j +++ b/Tests/Foundation/CPURLConnectionTest.j @@ -36,10 +36,4 @@ [self assertNull:data]; } -- (void)testRequestWithCredentials -{ - var connection = [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:@"Tests/Foundation/CPURLConnectionTest.j"] delegate:self withCredentials:YES]; - [self assertTrue:[connection withCredentials]]; -} - @end diff --git a/Tests/Objective-J/CFHTTPRequestTest.j b/Tests/Objective-J/CFHTTPRequestTest.j index f6afe5a58..c10edba85 100644 --- a/Tests/Objective-J/CFHTTPRequestTest.j +++ b/Tests/Objective-J/CFHTTPRequestTest.j @@ -7,10 +7,10 @@ - (void)testSetWithCredentials { var cfHTTPRequest = new CFHTTPRequest(); - [self assertFalse:cfHTTPRequest.getWithCredentials()]; + [self assertFalse:cfHTTPRequest.withCredentials()]; cfHTTPRequest.setWithCredentials(YES); - [self assertTrue:cfHTTPRequest.getWithCredentials()]; + [self assertTrue:cfHTTPRequest.withCredentials()]; } @end From 56b613ff8a762e5fb5bae0d3fdc7d138043b25be Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 18:05:38 -0500 Subject: [PATCH 4/9] Tests: Unit tests for CPURLRequest --- Tests/Foundation/CPURLRequestTest.j | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Tests/Foundation/CPURLRequestTest.j diff --git a/Tests/Foundation/CPURLRequestTest.j b/Tests/Foundation/CPURLRequestTest.j new file mode 100644 index 000000000..2c9cbdb72 --- /dev/null +++ b/Tests/Foundation/CPURLRequestTest.j @@ -0,0 +1,30 @@ +@import + + +var exampleURL = "http://www.cappuccino-project.org"; + +@implementation CPURLRequestTest : OJTestCase +{ +} + +- (void)testClassMethods +{ + var url = [CPURL URLWithString:exampleURL], + req = [CPURLRequest requestWithURL:url]; + + [self assert:[req HTTPMethod] equals:@"GET"]; + [self assert:[req URL] equals:url]; +} + +- (void)testWithCredentials +{ + var url = [CPURL URLWithString:exampleURL], + req = [CPURLRequest requestWithURL:url]; + + [self assertFalse:[req withCredentials]]; + + [req setWithCredentials:YES]; + [self assertTrue:[req withCredentials]]; +} + +@end \ No newline at end of file From 2db9fd9657f7c3955729aac886df344a1ea91a13 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 18:06:02 -0500 Subject: [PATCH 5/9] Test: Expand Unit tests for CPURLConnection These tests cover new methods added to CPURLConnection --- Tests/Foundation/CPURLConnectionTest.j | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Tests/Foundation/CPURLConnectionTest.j b/Tests/Foundation/CPURLConnectionTest.j index a7486abac..8d176c9e7 100644 --- a/Tests/Foundation/CPURLConnectionTest.j +++ b/Tests/Foundation/CPURLConnectionTest.j @@ -1,3 +1,4 @@ +@import @implementation CPURLConnectionTest : OJTestCase { @@ -36,4 +37,40 @@ [self assertNull:data]; } +- (void)testClassMethodConnectionWithCredentials +{ + var req = [CPURLRequest requestWithURL:[CPURL URLWithString:@"Tests/Foundation/CPURLConnectionTest.j"]]; + [req setWithCredentials:YES]; + var data = [CPURLConnection sendSynchronousRequest:req returningResponse:nil]; + + [self assertNotNull:data]; +} + +- (void)testInstanceMethodConnectionWithCredentials +{ + var req = [CPURLRequest requestWithURL:[CPURL URLWithString:@"Tests/Foundation/CPURLConnectionTest.j"]]; + [req setWithCredentials:YES]; + + var conn = [[CPURLConnection alloc] initWithRequest:req delegate:nil startImmediately:NO]; + + [self assertTrue:conn._HTTPRequest.withCredentials]; + + [req setWithCredentials:NO]; + [self assertTrue:conn._HTTPRequest.withCredentials]; +} + +- (void)testRequestGetters +{ + var req = [CPURLRequest requestWithURL:[CPURL URLWithString:@"Tests/Foundation/CPURLConnectionTest.j"]], + conn = [[CPURLConnection alloc] initWithRequest:req delegate:nil startImmediately:NO]; + + var originalRequest = [conn originalRequest], + currentRequest = [conn currentRequest]; + + [self assert:originalRequest._UID notEqual:currentRequest._UID]; + + [[conn currentRequest] setWithCredentials:YES]; + [self assert:[originalRequest withCredentials] notEqual:[currentRequest withCredentials]]; +} + @end From c7397187106cdeaade9517355c6bb44dd7b7189b Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 18:08:54 -0500 Subject: [PATCH 6/9] New: CPURLConnection now has the originalRequest and currentRequest methods Previously, CPURLConnection did not implement the originalRequest and currentRequest methods (added to Cocoa in 10.8). This commit adds this functionality. NB: this is dependent on CPURLRequest having deep-copy capabilities to make a copy of the original request, which has been added in another commit on this pull request. --- Foundation/CPURLConnection.j | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Foundation/CPURLConnection.j b/Foundation/CPURLConnection.j index 7c4cfd81e..5a4f09f26 100644 --- a/Foundation/CPURLConnection.j +++ b/Foundation/CPURLConnection.j @@ -76,7 +76,8 @@ var CPURLConnectionDelegate = nil; */ @implementation CPURLConnection : CPObject { - CPURLRequest _request; + CPURLRequest _originalRequest @accessors(readonly, getter=originalRequest); + CPURLRequest _request @accessors(readonly, getter=currentRequest); id _delegate; BOOL _isCanceled; BOOL _isLocalFileConnection; @@ -151,6 +152,7 @@ var CPURLConnectionDelegate = nil; if (self) { _request = aRequest; + _originalRequest = [aRequest copy]; _delegate = aDelegate; _isCanceled = NO; From c22cf71099db2867691694dd96b4616a0c9f1458 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 18:11:10 -0500 Subject: [PATCH 7/9] New: Added CPCopying protocol to CPURLRequest Previously it was not possible to deep-copy a CPURLRequest, which meant that a CPURLConnection could not keep track of both the original and modified versions of a request. This commit adds the copy method to CPURLRequest. --- Foundation/CPURLRequest.j | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Foundation/CPURLRequest.j b/Foundation/CPURLRequest.j index 3b93b8d06..c3d9aa40b 100644 --- a/Foundation/CPURLRequest.j +++ b/Foundation/CPURLRequest.j @@ -119,3 +119,23 @@ } @end + +/* + Implements the CPCopying Protocol for a CPURLRequest to provide deep copying for CPURLRequests +*/ +@implementation CPURLRequest (CPCopying) +{ +} + +- (id)copy +{ + var request = [[CPURLRequest alloc] initWithURL:[self URL]]; + [request setHTTPBody:[self HTTPBody]]; + [request setHTTPMethod:[self HTTPMethod]]; + [request setWithCredentials:[self withCredentials]]; + request._HTTPHeaderFields = [self allHTTPHeaderFields]; + + return request; +} + +@end From 2a16fb5e097a7a74c7a6fb001faf65e435c7e639 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 4 Dec 2014 18:11:38 -0500 Subject: [PATCH 8/9] Fixed: Properly initialize the _withCredentials variable in CPURLRequest --- Foundation/CPURLRequest.j | 1 + 1 file changed, 1 insertion(+) diff --git a/Foundation/CPURLRequest.j b/Foundation/CPURLRequest.j index c3d9aa40b..8d6a39e3b 100644 --- a/Foundation/CPURLRequest.j +++ b/Foundation/CPURLRequest.j @@ -80,6 +80,7 @@ _HTTPBody = @""; _HTTPMethod = @"GET"; _HTTPHeaderFields = @{}; + _withCredentials = NO; [self setValue:"Thu, 01 Jan 1970 00:00:00 GMT" forHTTPHeaderField:"If-Modified-Since"]; [self setValue:"no-cache" forHTTPHeaderField:"Cache-Control"]; From 642dc36c4197dcf06ecdf097ca5e9884852b9b6e Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Tue, 9 Dec 2014 16:07:43 -0500 Subject: [PATCH 9/9] Test: Cross Origin Manual Test This commit adds a manual testing application for checking Cross-origin behaviour in different browsers. A README file included in this application provides details on how to run the tests. --- Tests/Manual/CrossOriginTest/AppController.j | 78 + Tests/Manual/CrossOriginTest/Info.plist | 14 + Tests/Manual/CrossOriginTest/Jakefile | 184 ++ Tests/Manual/CrossOriginTest/README.md | 45 + .../CrossOriginTest/Resources/MainMenu.xib | 1759 +++++++++++++++++ Tests/Manual/CrossOriginTest/cors-server.py | 44 + Tests/Manual/CrossOriginTest/index-debug.html | 191 ++ Tests/Manual/CrossOriginTest/index.html | 161 ++ Tests/Manual/CrossOriginTest/main.j | 18 + Tests/Manual/CrossOriginTest/resp.json | 1 + 10 files changed, 2495 insertions(+) create mode 100644 Tests/Manual/CrossOriginTest/AppController.j create mode 100644 Tests/Manual/CrossOriginTest/Info.plist create mode 100644 Tests/Manual/CrossOriginTest/Jakefile create mode 100644 Tests/Manual/CrossOriginTest/README.md create mode 100644 Tests/Manual/CrossOriginTest/Resources/MainMenu.xib create mode 100644 Tests/Manual/CrossOriginTest/cors-server.py create mode 100644 Tests/Manual/CrossOriginTest/index-debug.html create mode 100644 Tests/Manual/CrossOriginTest/index.html create mode 100644 Tests/Manual/CrossOriginTest/main.j create mode 100644 Tests/Manual/CrossOriginTest/resp.json diff --git a/Tests/Manual/CrossOriginTest/AppController.j b/Tests/Manual/CrossOriginTest/AppController.j new file mode 100644 index 000000000..2d3781175 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/AppController.j @@ -0,0 +1,78 @@ +/* + * AppController.j + * CrossOriginTest + * + * Created by You on December 5, 2014. + * Copyright 2014, Your Company All rights reserved. + */ + +@import +@import + +var corsServer = "http://localhost:8001"; + +@implementation AppController : CPObject +{ + @outlet CPWindow theWindow; + @outlet CPButton theButton; + @outlet CPButton setsWithCredentials; +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ +} + +- (void)awakeFromCib +{ + // This is called when the cib is done loading. + // You can implement this method on any object instantiated from a Cib. + // It's a useful hook for setting up current UI values, and other things. + + // In this case, we want the window from Cib to become our full browser window + [theWindow setFullPlatformWindow:YES]; +} + +-(void)connection:(CPURLConnection)connection didReceiveResponse:(CPHTTPURLResponse)response +{ + console.log("Response received"); +} + +-(void)connection:(CPURLConnection)connection didReceiveData:(CPString)data +{ + var wc = ([[connection originalRequest] withCredentials]) ? "YES" : "NO" + console.log("CPURLConnection was sent with credentials? " + wc + " Response: " + data); +} + +- (@action)stateOfWithCredentials:(id)aSender +{ + console.log([setsWithCredentials state]); +} + +- (@action)testCappuccinoRequest:(id)aSender +{ + var req = [CPURLRequest requestWithURL:[CPURL URLWithString:corsServer + @"/resp.json"]]; + [req setValue:@"no-cache" forHTTPHeaderField:@"Pragma"]; + [req setValue:@"no-store, no-cache, must-revalidate, post-check=0, pre-check=0" forHTTPHeaderField:@"Cache-Control"]; + [req setWithCredentials:[setsWithCredentials state]]; + [[CPURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES]; +} + +- (@action)testNativeRequest:(id)aSender +{ + var wc = ([setsWithCredentials state]) ? true : false; + var req = new XMLHttpRequest(); + function reqListener () + { + console.log("Native XHR was sent with credentials? " + wc + " Response: " + this.responseText); + } + + req.onload = reqListener; + req.withCredentials = wc; + req.open("GET", corsServer + "/resp.json", true); + req.setRequestHeader("Pragma", "no-cache"); + req.setRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); + + req.send(); +} + +@end diff --git a/Tests/Manual/CrossOriginTest/Info.plist b/Tests/Manual/CrossOriginTest/Info.plist new file mode 100644 index 000000000..2074fa146 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/Info.plist @@ -0,0 +1,14 @@ + + + + + Main cib file base name + MainMenu.cib + CPBundleName + CrossOriginTest + CPBundleVersion + 1.0 + CPHumanReadableCopyright + Copyright © 2014, Your Company All rights reserved. + + diff --git a/Tests/Manual/CrossOriginTest/Jakefile b/Tests/Manual/CrossOriginTest/Jakefile new file mode 100644 index 000000000..6a448e9b0 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/Jakefile @@ -0,0 +1,184 @@ +/* + * Jakefile + * CrossOriginTest + * + * Created by You on December 9, 2014. + * Copyright 2014, Your Company All rights reserved. + */ + +var ENV = require("system").env, + FILE = require("file"), + JAKE = require("jake"), + task = JAKE.task, + FileList = JAKE.FileList, + app = require("cappuccino/jake").app, + configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug", + OS = require("os"), + projectName = "CrossOriginTest"; + +app (projectName, function(task) +{ + ENV["OBJJ_INCLUDE_PATHS"] = "Frameworks"; + + if (configuration === "Debug") + ENV["OBJJ_INCLUDE_PATHS"] = FILE.join(ENV["OBJJ_INCLUDE_PATHS"], configuration); + + task.setBuildIntermediatesPath(FILE.join("Build", "CrossOriginTest.build", configuration)); + task.setBuildPath(FILE.join("Build", configuration)); + + task.setProductName("CrossOriginTest"); + task.setIdentifier("com.yourcompany.CrossOriginTest"); + task.setVersion("1.0"); + task.setAuthor("Your Company"); + task.setEmail("feedback @nospam@ yourcompany.com"); + task.setSummary("CrossOriginTest"); + task.setSources(new FileList("**/*.j").exclude(FILE.join("Build", "**")).exclude(FILE.join("Frameworks", "Source", "**"))); + task.setResources(new FileList("Resources/**")); + task.setIndexFilePath("index.html"); + task.setInfoPlistPath("Info.plist"); + + if (configuration === "Debug") + task.setCompilerFlags("-DDEBUG -g"); + else + task.setCompilerFlags("-O"); +}); + +task ("default", [projectName], function() +{ + printResults(configuration); +}); + +task ("build", ["default"], function() +{ + updateApplicationSize(); +}); + +task ("debug", function() +{ + configuration = ENV["CONFIGURATION"] = "Debug"; + JAKE.subjake(["."], "build", ENV); +}); + +task ("release", function() +{ + configuration = ENV["CONFIGURATION"] = "Release"; + JAKE.subjake(["."], "build", ENV); +}); + +task ("run", ["debug"], function() +{ + OS.system(["open", FILE.join("Build", "Debug", projectName, "index.html")]); +}); + +task ("run-release", ["release"], function() +{ + OS.system(["open", FILE.join("Build", "Release", projectName, "index.html")]); +}); + +task ("deploy", ["release"], function() +{ + FILE.mkdirs(FILE.join("Build", "Deployment", projectName)); + OS.system(["press", "-f", FILE.join("Build", "Release", projectName), FILE.join("Build", "Deployment", projectName)]); + printResults("Deployment") +}); + +task ("desktop", ["release"], function() +{ + FILE.mkdirs(FILE.join("Build", "Desktop", projectName)); + require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", projectName), FILE.join("Build", "Desktop", projectName, "CrossOriginTest.app")); + printResults("Desktop") +}); + +task ("run-desktop", ["desktop"], function() +{ + OS.system([FILE.join("Build", "Desktop", projectName, "CrossOriginTest.app", "Contents", "MacOS", "NativeHost"), "-i"]); +}); + +function printResults(configuration) +{ + print("----------------------------"); + print(configuration+" app built at path: "+FILE.join("Build", configuration, projectName)); + print("----------------------------"); +} + +function updateApplicationSize() +{ + print("Calculating application file sizes..."); + + var contents = FILE.read(FILE.join("Build", configuration, projectName, "Info.plist"), { charset:"UTF-8" }), + format = CFPropertyList.sniffedFormatOfString(contents), + plist = CFPropertyList.propertyListFromString(contents), + totalBytes = {executable:0, data:0, mhtml:0}; + + // Get the size of all framework executables and sprite data + var frameworksDir = "Frameworks"; + + if (configuration === "Debug") + frameworksDir = FILE.join(frameworksDir, "Debug"); + + var frameworks = FILE.list(frameworksDir); + + frameworks.forEach(function(framework) + { + if (framework !== "Source") + addBundleFileSizes(FILE.join(frameworksDir, framework), totalBytes); + }); + + // Read in the default theme name, and attempt to get its size + var themeName = plist.valueForKey("CPDefaultTheme") || "Aristo2", + themePath = nil; + + if (themeName === "Aristo" || themeName === "Aristo2") + themePath = FILE.join(frameworksDir, "AppKit", "Resources", themeName + ".blend"); + else + themePath = FILE.join("Frameworks", "Resources", themeName + ".blend"); + + if (FILE.isDirectory(themePath)) + addBundleFileSizes(themePath, totalBytes); + + // Add sizes for the app + addBundleFileSizes(FILE.join("Build", configuration, projectName), totalBytes); + + print("Executables: " + totalBytes.executable + ", sprite data: " + totalBytes.data + ", total: " + (totalBytes.executable + totalBytes.data)); + + var dict = new CFMutableDictionary(); + + dict.setValueForKey("executable", totalBytes.executable); + dict.setValueForKey("data", totalBytes.data); + dict.setValueForKey("mhtml", totalBytes.mhtml); + + plist.setValueForKey("CPApplicationSize", dict); + + FILE.write(FILE.join("Build", configuration, projectName, "Info.plist"), CFPropertyList.stringFromPropertyList(plist, format), { charset:"UTF-8" }); +} + +function addBundleFileSizes(bundlePath, totalBytes) +{ + var bundleName = FILE.basename(bundlePath), + environment = bundleName === "Foundation" ? "Objj" : "Browser", + bundlePath = FILE.join(bundlePath, environment + ".environment"); + + if (FILE.isDirectory(bundlePath)) + { + var filename = bundleName + ".sj", + filePath = new FILE.Path(FILE.join(bundlePath, filename)); + + if (filePath.exists()) + totalBytes.executable += filePath.size(); + + filePath = new FILE.Path(FILE.join(bundlePath, "dataURLs.txt")); + + if (filePath.exists()) + totalBytes.data += filePath.size(); + + filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLData.txt")); + + if (filePath.exists()) + totalBytes.mhtml += filePath.size(); + + filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLPaths.txt")); + + if (filePath.exists()) + totalBytes.mhtml += filePath.size(); + } +} diff --git a/Tests/Manual/CrossOriginTest/README.md b/Tests/Manual/CrossOriginTest/README.md new file mode 100644 index 000000000..6c50ecada --- /dev/null +++ b/Tests/Manual/CrossOriginTest/README.md @@ -0,0 +1,45 @@ +This test checks the withCredentials CORS functionality with Cappuccino. + +Running the test: + +You will need to start two HTTP Servers; one on localhost:8000, and one on localhost:8001. + +The first: + +`$> python -m SimpleHTTPServer` // starts it on 8000 + +In another terminal window: + +`$> python cors-server.py` // starts another on 8001 + +Visit http://localhost:8000 in your web browser. There are two buttons and a checkbox. + +One button will issue a native XMLHTTPRequest. The other will issue a CPURLConnection request. The checkbox will control whether the withCredentials option is set on both types of requests. + +With the checkbox checked, you should press either of the buttons. In the terminal with the 'cors-server.py' script running you will see output that should match the following: + +``` +INFO:root:CORS: With Credentials +127.0.0.1 - - [05/Dec/2014 18:44:48] "GET /resp.json HTTP/1.1" 200 - +``` + +If you uncheck the checkbox, you should see the following: + +``` +INFO:root:CORS: No Credentials +127.0.0.1 - - [05/Dec/2014 18:44:56] "GET /resp.json HTTP/1.1" 200 - +``` + +This error message is controlled by the presence of the 'Cookies' header. + +NOTE: The cors-server.py will set a cookie for you (mycookie=cappuccino!), but only after the first request. If you don't have a cookie set for localhost, the server message will show 'No Credentials' on the first request since the Cookie header is not set. Subsequent requests will behave correctly. + +The browser console will also provide some status information about the request and response. + +# A note about IE** + +As best I can tell, IE behaves differently than all other browsers. I have tested this in Chrome and Firefox on Mac & Windows, Safari on Mac, IE11 on Windows. In this test, unchecking the 'With Credentials' will tell the browser to not send a cookie to the server if the server and client are not on the same host. However, in IE, it will pass the cookie along if the server and host are on the same top domain, but not necessarily the same host. The corollary of this is that if the two servers are on different domains, the `withCredentials` setting in IE does absolutely nothing. + +To get it to work, you must instruct your users to adjust their cookie privacy settings and allow third-party cookies. This seemed to work for me, but dynamically adjusting the `withCredentials` parameter did nothing with this on -- IE always sent the cookies if it was configured to do so. + +* What, you expected IE to actually work like the rest of the world? \ No newline at end of file diff --git a/Tests/Manual/CrossOriginTest/Resources/MainMenu.xib b/Tests/Manual/CrossOriginTest/Resources/MainMenu.xib new file mode 100644 index 000000000..a9914bcd6 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/Resources/MainMenu.xib @@ -0,0 +1,1759 @@ + + + + 1050 + 14B25 + 6250 + 1343.16 + 755.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 6250 + + + NSButton + NSButtonCell + NSCustomObject + NSMenu + NSMenuItem + NSView + NSWindowTemplate + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + NewApplication + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + + NewApplication + + + + About NewApplication + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit NewApplication + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + + Spelling and Grammar + + + + Show Spelling… + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + + Substitutions + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + + Help + + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 7 + 2 + {{335, 390}, {480, 360}} + 1946157056 + Window + NSWindow + + + + + 256 + + + + 268 + {{142, 196}, {197, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Native XMLHTTPRequest + + YES + 13 + 1044 + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{133, 163}, {215, 32}} + + + _NS:9 + YES + + 67108864 + 134217728 + Cappuccino CPURLRequest + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{178, 272}, {124, 18}} + + + + _NS:9 + YES + + -2080374784 + 268435456 + With Credentials + + _NS:9 + + 1211912448 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + NO + + + {480, 360} + + + + + {{0, 0}, {1920, 1177}} + {10000000000000, 10000000000000} + YES + + + AppController + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 451 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + theButton + + + + 462 + + + + theWindow + + + + 463 + + + + setsWithCredentials + + + + 471 + + + + stateOfWithCredentials: + + + + 472 + + + + testNativeRequest: + + + + 473 + + + + testCappuccinoRequest: + + + + 474 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + MainMenu + + + 19 + + + + + + + + 56 + + + + + + + + 103 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + + + + + + 111 + + + + + 57 + + + + + + + + + + + + 58 + + + + + 136 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + + + + 372 + + + + + + + + + + 450 + + + + + 460 + + + + + + + + 461 + + + + + 465 + + + + + + + + 466 + + + + + 468 + + + + + + + + 469 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{303, 221}, {480, 360}} + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 474 + + + + + AppController + NSObject + + id + id + id + + + + stateOfWithCredentials: + id + + + testCappuccinoRequest: + id + + + testNativeRequest: + id + + + + NSButton + NSButton + NSWindow + + + + setsWithCredentials + NSButton + + + theButton + NSButton + + + theWindow + NSWindow + + + + IBProjectSource + ../.XcodeSupport/AppController.h + + + + + 0 + IBCocoaFramework + NO + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {12, 12} + {10, 2} + {15, 15} + + + diff --git a/Tests/Manual/CrossOriginTest/cors-server.py b/Tests/Manual/CrossOriginTest/cors-server.py new file mode 100644 index 000000000..937f2188a --- /dev/null +++ b/Tests/Manual/CrossOriginTest/cors-server.py @@ -0,0 +1,44 @@ +import SimpleHTTPServer +import SocketServer +import logging +import cgi + +logging.basicConfig(level=logging.INFO) +PORT = 8001 + +class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): + + def end_headers (self): + self.send_header('Set-Cookie', 'mycookie=cappuccino!') + self.send_header('Access-Control-Allow-Origin', 'http://142.157.142.237:8000') + self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS') + self.send_header("Access-Control-Allow-Headers", "X-Requested-With, If-Modified-Since, Cache-Control, Pragma") + self.send_header('Access-Control-Allow-Credentials', 'true') + SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) + + def do_OPTIONS(self): + logging.info("OPTIONS Request") + self.send_response(204, "No Content") + self.send_header('Access-Control-Allow-Origin', 'http://142.157.142.237:8000') + self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS') + self.send_header("Access-Control-Allow-Headers", "X-Requested-With, If-Modified-Since, Cache-Control, Pragma") + self.send_header('Access-Control-Allow-Credentials', 'true') + self.send_header("Access-Control-Max-Age", 10) + self.send_header("content-length", 0) + + def do_GET(self): + try: + self.headers['Cookie'] + logging.info("CORS: With Credentials") + logging.info(self.headers['Cookie']) + except KeyError, e: + logging.info("CORS: No Credentials") + SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) + +Handler = ServerHandler + +SocketServer.TCPServer.allow_reuse_address = True +httpd = SocketServer.TCPServer(("0.0.0.0", PORT), Handler) + +print "serving at port", PORT +httpd.serve_forever() \ No newline at end of file diff --git a/Tests/Manual/CrossOriginTest/index-debug.html b/Tests/Manual/CrossOriginTest/index-debug.html new file mode 100644 index 000000000..59a519b3d --- /dev/null +++ b/Tests/Manual/CrossOriginTest/index-debug.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + TestIEWithCredentials + + + + + + + + + + + + + + +
+
+
+ +
+
+ +
+ + diff --git a/Tests/Manual/CrossOriginTest/index.html b/Tests/Manual/CrossOriginTest/index.html new file mode 100644 index 000000000..b38196c63 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/index.html @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + CrossOriginTest + + + + + + + + + + + + +
+
+
+ +
+
+ +
+ + diff --git a/Tests/Manual/CrossOriginTest/main.j b/Tests/Manual/CrossOriginTest/main.j new file mode 100644 index 000000000..fb705f3f3 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/main.j @@ -0,0 +1,18 @@ +/* + * AppController.j + * CrossOriginTest + * + * Created by You on December 9, 2014. + * Copyright 2014, Your Company All rights reserved. + */ + +@import +@import + +@import "AppController.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} diff --git a/Tests/Manual/CrossOriginTest/resp.json b/Tests/Manual/CrossOriginTest/resp.json new file mode 100644 index 000000000..5d76ff1e6 --- /dev/null +++ b/Tests/Manual/CrossOriginTest/resp.json @@ -0,0 +1 @@ +{"response": "ok"} \ No newline at end of file