Commits

Adam Pritchard committed 2a96e16

Feedback revamp in progress

Comments (0)

Files changed (8)

Automation/FeedbackSite/Templates/feedback.html.tpl

     return 'en';
 }}
 
+var diagnosticInfoID = '';
+
 //sets page content and highlights coerresponding language button
 function setLanguage(langName)
 {{
     var PLATFORM_WINDOWS = 'windows', PLATFORM_ANDROID = 'android';
     var platform = (window.dialogArguments !== undefined) ? PLATFORM_WINDOWS : PLATFORM_ANDROID;
 
-    var emailModifier = '';
+    var diagnosticInfoIDEmailModifier = '';
     if (platform === PLATFORM_WINDOWS) {{
-      emailModifier = $.parseJSON(window.dialogArguments)['emailModifier'];
+      diagnosticInfoID = $.parseJSON(window.dialogArguments)['diagnosticInfoID'];
+      diagnosticInfoIDEmailModifier = '+' + diagnosticInfoID;
     }}
 
     $.each(currentLanguage, function(name, val){{
             // Replace the feedback address with a platform specific value.
             val = val.replace(
                         /([a-z0-9]+)@([^\.]+)\.([a-z]+)/g,
-                        "$1+" + platform + emailModifier + "@$2.$3");
+                        "$1+" + platform + diagnosticInfoIDEmailModifier + "@$2.$3");
             $(selector).html(val);
         }}
         else {{
         responses.push({{question:hash, answer: 2}});
       }}
     }});
-    s = $.stringify({{"responses":responses}});
+    s = $.stringify({{
+      'responses':responses,
+      'diagnosticInfoID': $('#sendDiagnostic').attr('checked') ? diagnosticInfoID : ''
+    }});
 
     //Windows client expects result in the window.returnValue magic variable
     //No need to actually submit data
-    if(window.dialogArguments !== undefined) {{
+    if (window.dialogArguments !== undefined) {{
       window.returnValue = s;
       window.close();
     }}
     e.preventDefault();
     if(window.dialogArguments !== undefined) {{
       window.returnValue = $.stringify({{
-        "emailAddress": $('#emailAddress').text(),
-        "emailAddressEncoded": encodeURIComponent($('#emailAddress').text()),
-        "sendDiagnostic": !!$('#sendDiagnostic').attr('checked')
+        'emailAddress': $('#emailAddress').text(),
+        'emailAddressEncoded': encodeURIComponent($('#emailAddress').text()),
+        'diagnosticInfoID': $('#sendDiagnostic').attr('checked') ? diagnosticInfoID : ''
       }});
       window.close();
     }}

Automation/FeedbackSite/feedback.html

     return 'en';
 }
 
+var diagnosticInfoID = '';
+
 //sets page content and highlights coerresponding language button
 function setLanguage(langName)
 {
     var PLATFORM_WINDOWS = 'windows', PLATFORM_ANDROID = 'android';
     var platform = (window.dialogArguments !== undefined) ? PLATFORM_WINDOWS : PLATFORM_ANDROID;
 
-    var emailModifier = '';
+    var diagnosticInfoIDEmailModifier = '';
     if (platform === PLATFORM_WINDOWS) {
-      emailModifier = $.parseJSON(window.dialogArguments)['emailModifier'];
+      diagnosticInfoID = $.parseJSON(window.dialogArguments)['diagnosticInfoID'];
+      diagnosticInfoIDEmailModifier = '+' + diagnosticInfoID;
     }
 
     $.each(currentLanguage, function(name, val){
             // Replace the feedback address with a platform specific value.
             val = val.replace(
                         /([a-z0-9]+)@([^\.]+)\.([a-z]+)/g,
-                        "$1+" + platform + emailModifier + "@$2.$3");
+                        "$1+" + platform + diagnosticInfoIDEmailModifier + "@$2.$3");
             $(selector).html(val);
         }
         else {
         responses.push({question:hash, answer: 2});
       }
     });
-    s = $.stringify({"responses":responses});
+    s = $.stringify({
+      'responses':responses,
+      'diagnosticInfoID': $('#sendDiagnostic').attr('checked') ? diagnosticInfoID : ''
+    });
 
     //Windows client expects result in the window.returnValue magic variable
     //No need to actually submit data
-    if(window.dialogArguments !== undefined) {
+    if (window.dialogArguments !== undefined) {
       window.returnValue = s;
       window.close();
     }
     e.preventDefault();
     if(window.dialogArguments !== undefined) {
       window.returnValue = $.stringify({
-        "emailAddress": $('#emailAddress').text(),
-        "emailAddressEncoded": encodeURIComponent($('#emailAddress').text()),
-        "sendDiagnostic": !!$('#sendDiagnostic').attr('checked')
+        'emailAddress': $('#emailAddress').text(),
+        'emailAddressEncoded': encodeURIComponent($('#emailAddress').text()),
+        'diagnosticInfoID': $('#sendDiagnostic').attr('checked') ? diagnosticInfoID : ''
       });
       window.close();
     }

Client/psiclient/connectionmanager.cpp

 struct FeedbackThreadData
 {
     ConnectionManager* connectionManager;
-    wstring feedback;
+    wstring feedbackJSON;
 } g_feedbackThreadData;
 
-void ConnectionManager::SendFeedback(LPCWSTR feedback)
+void ConnectionManager::SendFeedback(LPCWSTR feedbackJSON)
 {
     g_feedbackThreadData.connectionManager = this;
-    g_feedbackThreadData.feedback = feedback;
+    g_feedbackThreadData.feedbackJSON = feedbackJSON;
 
     if (!m_feedbackThread ||
         WAIT_OBJECT_0 == WaitForSingleObject(m_feedbackThread, 0))
     {
-        if (!(m_feedbackThread = CreateThread(0, 0, ConnectionManager::ConnectionManagerFeedbackThread, (void*)&g_feedbackThreadData, 0, 0)))
+        if (!(m_feedbackThread = CreateThread(
+                                    0, 
+                                    0, 
+                                    ConnectionManager::ConnectionManagerFeedbackThread, 
+                                    (void*)&g_feedbackThreadData, 0, 0)))
         {
             my_print(false, _T("%s: CreateThread failed (%d)"), __TFUNCTION__, GetLastError());
             PostMessage(g_hWnd, WM_PSIPHON_FEEDBACK_FAILED, 0, 0);
 
     FeedbackThreadData* data = (FeedbackThreadData*)object;
 
-    if (data->connectionManager->DoSendFeedback(data->feedback.c_str()))
+    if (data->connectionManager->DoSendFeedback(data->feedbackJSON.c_str()))
     {
         PostMessage(g_hWnd, WM_PSIPHON_FEEDBACK_SUCCESS, 0, 0);
     }
     return 0;
 }
 
-bool ConnectionManager::DoSendFeedback(LPCWSTR feedback)
+bool ConnectionManager::DoSendFeedback(LPCWSTR feedbackJSON)
 {
     // NOTE: no lock while waiting for network events
 
         sessionInfo = m_currentSessionInfo;
     }
 
-    string narrowFeedback;
-    if (feedback)
+    string narrowFeedbackJSON = TStringToNarrow(feedbackJSON);
+    Json::Value json_entry;
+    Json::Reader reader;
+    if (!reader.parse(narrowFeedbackJSON, json_entry))
     {
-        narrowFeedback = WStringToNarrow(feedback);
+        assert(0);
+        return false;
     }
 
-    tstring requestPath = GetFeedbackRequestPath(m_transport);
-    string response;
+    string emailAddress = json_entry.get("emailAddress", "").asString();
+    string emailAddressEncoded = json_entry.get("emailAddressEncoded", "").asString();
+    string diagnosticInfoID = json_entry.get("diagnosticInfoID", "").asString();
 
     // When disconnected, ignore the user cancel flag in the HTTP request
     // wait loop.
     // a shorter timeout in this case
     DWORD stopReason = (GetState() == CONNECTION_MANAGER_STATE_CONNECTED ? STOP_REASON_ALL : STOP_REASON_NONE);
 
-    bool success = ServerRequest::MakeRequest(
-                        ServerRequest::NO_TEMP_TUNNEL,
-                        m_transport,
-                        sessionInfo,
-                        requestPath.c_str(),
-                        response,
-                        StopInfo(&GlobalStopSignal::Instance(), stopReason),
-                        L"Content-Type: application/json",
-                        (LPVOID)narrowFeedback.c_str(),
-                        narrowFeedback.length());
+    bool success = true;
+
+    // Two different actions might be required at this point:
+    // 1) The user wishes to send a feedback email (optionally uploading diagnostic info).
+    // 2) The user completed the questionnaire and wishes to submit it.
+
+    if (emailAddress.length() > 0)
+    {
+        // We don't care if this succeeds.
+        (void)OpenEmailAndSendDiagnosticInfo(
+                emailAddress,
+                emailAddressEncoded,
+                diagnosticInfoID,
+                StopInfo(&GlobalStopSignal::Instance(), stopReason));
+    }
+    else
+    {
+        // Send the feedback questionnaire responses
+
+        tstring requestPath = GetFeedbackRequestPath(m_transport);
+        string response;
+
+        success = ServerRequest::MakeRequest(
+                            ServerRequest::NO_TEMP_TUNNEL,
+                            m_transport,
+                            sessionInfo,
+                            requestPath.c_str(),
+                            response,
+                            StopInfo(&GlobalStopSignal::Instance(), stopReason),
+                            L"Content-Type: application/json",
+                            (LPVOID)narrowFeedbackJSON.c_str(),
+                            narrowFeedbackJSON.length());
+
+        // Upload diagnostic info
+        if (diagnosticInfoID.length() > 0) 
+        {
+            // We don't care if this succeeds.
+            (void)OpenEmailAndSendDiagnosticInfo(
+                    string(),  // don't email
+                    string(), 
+                    diagnosticInfoID,
+                    StopInfo(&GlobalStopSignal::Instance(), stopReason));
+        }
+    }
 
     return success;
 }

Client/psiclient/connectionmanager.h

 
     // Results in WM_PSIPHON_FEEDBACK_SUCCESS being posted to the main window
     // on success, WM_PSIPHON_FEEDBACK_FAILED on failure.
-    void SendFeedback(LPCWSTR feedback);
+    void SendFeedback(LPCWSTR feedbackJSON);
 
 private:
     static DWORD WINAPI ConnectionManagerStartThread(void* object);
     void CopyCurrentSessionInfo(SessionInfo& sessionInfo);
     void UpdateCurrentSessionInfo(const SessionInfo& sessionInfo);
 
-    bool DoSendFeedback(LPCWSTR feedback);
+    bool DoSendFeedback(LPCWSTR feedbackJSON);
     static DWORD WINAPI ConnectionManagerFeedbackThread(void* object);
 
 private:

Client/psiclient/feedback.html

     return 'en';
 }
 
+var diagnosticInfoID = '';
+
 //sets page content and highlights coerresponding language button
 function setLanguage(langName)
 {
     var PLATFORM_WINDOWS = 'windows', PLATFORM_ANDROID = 'android';
     var platform = (window.dialogArguments !== undefined) ? PLATFORM_WINDOWS : PLATFORM_ANDROID;
 
-    var emailModifier = '';
+    var diagnosticInfoIDEmailModifier = '';
     if (platform === PLATFORM_WINDOWS) {
-      emailModifier = $.parseJSON(window.dialogArguments)['emailModifier'];
+      diagnosticInfoID = $.parseJSON(window.dialogArguments)['diagnosticInfoID'];
+      diagnosticInfoIDEmailModifier = '+' + diagnosticInfoID;
     }
 
     $.each(currentLanguage, function(name, val){
             // Replace the feedback address with a platform specific value.
             val = val.replace(
                         /([a-z0-9]+)@([^\.]+)\.([a-z]+)/g,
-                        "$1+" + platform + emailModifier + "@$2.$3");
+                        "$1+" + platform + diagnosticInfoIDEmailModifier + "@$2.$3");
             $(selector).html(val);
         }
         else {
         responses.push({question:hash, answer: 2});
       }
     });
-    s = $.stringify({"responses":responses});
+    s = $.stringify({
+      'responses':responses,
+      'diagnosticInfoID': $('#sendDiagnostic').attr('checked') ? diagnosticInfoID : ''
+    });
 
     //Windows client expects result in the window.returnValue magic variable
     //No need to actually submit data
-    if(window.dialogArguments !== undefined) {
+    if (window.dialogArguments !== undefined) {
       window.returnValue = s;
       window.close();
     }
     e.preventDefault();
     if(window.dialogArguments !== undefined) {
       window.returnValue = $.stringify({
-        "emailAddress": $('#emailAddress').text(),
-        "emailAddressEncoded": encodeURIComponent($('#emailAddress').text()),
-        "sendDiagnostic": !!$('#sendDiagnostic').attr('checked')
+        'emailAddress': $('#emailAddress').text(),
+        'emailAddressEncoded': encodeURIComponent($('#emailAddress').text()),
+        'diagnosticInfoID': $('#sendDiagnostic').attr('checked') ? diagnosticInfoID : ''
       });
       window.close();
     }

Client/psiclient/psiclient.cpp

             byte randBytes[randBytesLen];
             rng.GenerateBlock(randBytes, randBytesLen);
             
-            tstring args = _T("{\"emailModifier\": \"+") + NarrowToTString(Hexlify(randBytes, randBytesLen)) + _T("\"}");
+            tstring args = _T("{\"diagnosticInfoID\": \"") + NarrowToTString(Hexlify(randBytes, randBytesLen)) + _T("\"}");
             
             tstring feedbackResult;
             if (ShowHTMLDlg(
                     args.c_str(),
                     feedbackResult) == 1)
             {
-                // Two different actions might be required at this point:
-                // 1) The user wishes to send a feedback email (optionally uploading diagnostic info).
-                // 2) The user completed the questionnaire and wishes to submit it.
+                my_print(false, _T("Thank you for the feedback!"));
 
-                string emailAddress, emailAddressEncoded;
-                bool sendDiagnosticInfo = false;
+                g_connectionManager.SendFeedback(feedbackResult.c_str());
 
-                Json::Value json_entry;
-                Json::Reader reader;
-                if (reader.parse(TStringToNarrow(feedbackResult), json_entry))
-                {
-                    emailAddress = json_entry.get("emailAddress", "").asString();
-                    emailAddressEncoded = json_entry.get("emailAddressEncoded", "").asString();
-                    sendDiagnosticInfo = json_entry.get("sendDiagnostic", false).asBool();
-                }
-
-                if (emailAddress.length() > 0)
-                {
-                    if (OpenEmailAndSendDiagnosticInfo(
-                            emailAddress, 
-                            emailAddressEncoded,
-                            sendDiagnosticInfo,
-                            StopInfo(&GlobalStopSignal::Instance(), STOP_REASON_EXIT)))
-                    {
-                        my_print(false, _T("Email address has been copied to clipboard"));
-                    }
-                }
-                else // Feedback questionnaire
-                {
-                    my_print(false, _T("Sending feedback..."));
-
-                    g_connectionManager.SendFeedback(feedbackResult.c_str());
-
-                    SendMessage(
-                        g_hFeedbackButton,
-                        BM_SETIMAGE,
-                        IMAGE_ICON,
-                        (LPARAM)g_hFeedbackButtonIcons[1]);
-                    EnableWindow(g_hFeedbackButton, FALSE);
-                }
+                SendMessage(
+                    g_hFeedbackButton,
+                    BM_SETIMAGE,
+                    IMAGE_ICON,
+                    (LPARAM)g_hFeedbackButtonIcons[1]);
+                EnableWindow(g_hFeedbackButton, FALSE);
             }
             // else error or user cancelled
         }

Client/psiclient/utilities.cpp

 bool OpenEmailAndSendDiagnosticInfo(
         const string& emailAddress, 
         const string& emailAddressEncoded, 
-        bool sendDiagnosticInfo, 
+        const string& diagnosticInfoID, 
         const StopInfo& stopInfo)
 {
-    //
-    // First put the address into the clipboard
-    //
+    if (emailAddress.length() > 0)
+    {
+        assert(emailAddressEncoded.length() > 0);
+        //
+        // First put the address into the clipboard
+        //
 
-    if (!OpenClipboard(NULL))
-    {
-        return false;
+        if (!OpenClipboard(NULL))
+        {
+            return false;
+        }
+
+        // Remove the current Clipboard contents 
+        if( !EmptyClipboard() )
+        {
+            return false;
+        }
+   
+        // Get the currently selected data
+        HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, emailAddress.length()+1);
+        strcpy_s((char*)hGlob, emailAddress.length()+1, emailAddress.c_str());
+    
+        // Note that the system takes ownership of hGlob
+        if (::SetClipboardData( CF_TEXT, hGlob ) == NULL)
+        {
+            CloseClipboard();
+            GlobalFree(hGlob);
+            return false;
+        }
+
+        CloseClipboard();
+
+        //
+        // Launch the email handler
+        //
+
+        string command = "mailto:" + emailAddress;
+
+        (void)::ShellExecuteA( 
+                    NULL, 
+                    "open", 
+                    command.c_str(), 
+                    NULL, 
+                    NULL, 
+                    SW_SHOWNORMAL); 
+
+        // TODO: What does ShellExecute return if there's no registered mailto handler?
+        // For now: Don't bother checking the return value at all. We've copied the
+        // address to the clipboard and that will have to be good enough.
     }
 
-    // Remove the current Clipboard contents 
-    if( !EmptyClipboard() )
-    {
-        return false;
-    }
-   
-    // Get the currently selected data
-    HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, emailAddress.length()+1);
-    strcpy_s((char*)hGlob, emailAddress.length()+1, emailAddress.c_str());
-    
-    // Note that the system takes ownership of hGlob
-    if (::SetClipboardData( CF_TEXT, hGlob ) == NULL)
-    {
-        CloseClipboard();
-        GlobalFree(hGlob);
-        return false;
-    }
-
-    CloseClipboard();
-
-    //
-    // Launch the email handler
-    //
-
-    string command = "mailto:" + emailAddress;
-
-    HINSTANCE hInst = ::ShellExecuteA( 
-                            NULL, 
-                            "open", 
-                            command.c_str(), 
-                            NULL, 
-                            NULL, 
-                            SW_SHOWNORMAL); 
-
-    // TODO: What does ShellExecute return if there's no registered mailto handler?
-    // For now: Don't bother checking the return value at all. We've copied the
-    // address to the clipboard and that will have to be good enough.
-
     //
     // Upload the diagnostic info
     //
 
-    if (sendDiagnosticInfo)
+    if (diagnosticInfoID.length() > 0)
     {
         string diagnosticInfo = "PUT SOME STUFF HERE";
 
         }
 
         tstring uploadLocation = NarrowToTString(FEEDBACK_DIAGNOSTIC_INFO_UPLOAD_PATH)
-                                    + NarrowToTString(emailAddress);
+                                    + NarrowToTString(diagnosticInfoID);
         
         string response;
         HTTPSRequest httpsRequest;

Client/psiclient/utilities.h

 bool PublicKeyEncryptData(const char* publicKey, const char* plaintext, string& o_encrypted);
 
 /**
-Attempts to initiate an email to the given address. Also puts the address into
-the clipboad in case there is no mailto handler.
-Optionally uploads associated diagnostic info.
+Attempts to initiate an email to the given address. Puts the email address into
+the clipboad in case there is no mailto handler. 
+Also uploads encrypted diagnostic information.
+Both `emailAddress` and `diagnosticInfoID` are optional.
 */
 bool OpenEmailAndSendDiagnosticInfo(
         const string& emailAddress, 
         const string& emailAddressEncoded, 
-        bool sendDiagnosticInfo,
+        const string& diagnosticInfoID, 
         const StopInfo& stopInfo);